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 |
No files matched your search
+189
-7
@@ -1,18 +1,21 @@
|
|||||||
//Functions.c
|
//Functions.c
|
||||||
//05/07/03 Josh Holtrop
|
//05/07/03 Josh Holtrop
|
||||||
//for HOS
|
//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
|
inline void outportb(unsigned int port, unsigned char value) // Output a byte to a port
|
||||||
{
|
{
|
||||||
asm volatile ("outb %%al,%%dx"::"d" (port), "a" (value));
|
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
|
inline void outportw(unsigned int port, unsigned int value) // Output a word to a port
|
||||||
{
|
{
|
||||||
asm volatile ("outw %%ax,%%dx"::"d" (port), "a" (value));
|
asm volatile ("outw %%ax,%%dx"::"d" (port), "a" (value));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Reads a byte from a port
|
||||||
inline byte inportb(unsigned short port)
|
inline byte inportb(unsigned short port)
|
||||||
{
|
{
|
||||||
unsigned char ret_val;
|
unsigned char ret_val;
|
||||||
@@ -23,16 +26,82 @@ inline byte inportb(unsigned short port)
|
|||||||
return ret_val;
|
return ret_val;
|
||||||
};
|
};
|
||||||
|
|
||||||
void enable_ints()
|
//Enables (SeTs) Interrupt Flag on the processor
|
||||||
|
inline void enable_ints()
|
||||||
{
|
{
|
||||||
asm("sti");
|
asm("sti");
|
||||||
};
|
};
|
||||||
|
|
||||||
void disable_ints()
|
//Disables (CLears) Interrupt Flag on the processor
|
||||||
|
inline void disable_ints()
|
||||||
{
|
{
|
||||||
asm("cli");
|
asm("cli");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
char *strcat(char *dest, char *src)
|
||||||
|
{
|
||||||
|
strcpy(dest+strlen(dest), src);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//converts a binary-coded-decimal byte to its decimal equivalent
|
||||||
|
inline byte bcd2byte(byte bcd)
|
||||||
|
{
|
||||||
|
return (10* ((bcd & 0xF0) >> 4)) + (bcd & 0x0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
//converts a binary-coded-decimal byte to its decimal equivalent
|
||||||
|
inline byte byte2bcd(byte bite)
|
||||||
|
{
|
||||||
|
return ((bite / 10) << 4) | (bite % 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtrim(char *str)
|
||||||
|
{
|
||||||
|
str += strlen(str); //now points to the null character at the end of the string
|
||||||
|
str--;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if ((*str == ' ') || (*str == '\t') || (*str == '\n'))
|
||||||
|
*str-- = 0;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *ucase(char *str)
|
||||||
|
{
|
||||||
|
char *ret = str;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (*str == 0)
|
||||||
|
break;
|
||||||
|
if ((*str >= 'a') && (*str <= 'z'))
|
||||||
|
*str = (*str) - 32;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *lcase(char *str)
|
||||||
|
{
|
||||||
|
char *ret = str;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (*str == 0)
|
||||||
|
break;
|
||||||
|
if ((*str >= 'A') && (*str <= 'Z'))
|
||||||
|
*str = (*str) + 32;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Re-maps the Programmable Interrupr Controllers so IRQ0->pic1 base address, IRG8->pic2 base address
|
||||||
void remap_pics(int pic1, int pic2)
|
void remap_pics(int pic1, int pic2)
|
||||||
{
|
{
|
||||||
byte a1, a2;
|
byte a1, a2;
|
||||||
@@ -53,37 +122,150 @@ void remap_pics(int pic1, int pic2)
|
|||||||
outportb(PIC2_DATA, a2); //0xA1
|
outportb(PIC2_DATA, a2); //0xA1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Masks interrupts on first Programmable Interrupt Controller
|
||||||
inline void pic1_mask(byte mask)
|
inline void pic1_mask(byte mask)
|
||||||
{
|
{
|
||||||
outportb(PIC1_DATA, mask); //0x21, maskfield *OCW1*
|
outportb(PIC1_DATA, mask); //0x21, maskfield *OCW1*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Masks interrupts on second Programmable Interrupt Controller
|
||||||
inline void pic2_mask(byte mask)
|
inline void pic2_mask(byte mask)
|
||||||
{
|
{
|
||||||
outportb(PIC2_DATA, mask); //0xA1, maskfield *OCW1*
|
outportb(PIC2_DATA, mask); //0xA1, maskfield *OCW1*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Restarts the computer
|
||||||
inline void restart()
|
inline void restart()
|
||||||
{
|
{
|
||||||
|
enable_ints();
|
||||||
|
byte temp;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
temp = inportb(0x64);
|
||||||
|
if (temp & 1)
|
||||||
|
inportb(0x60);
|
||||||
|
} while(temp & 2);
|
||||||
|
|
||||||
|
|
||||||
outportb (0x64, 0xfe);
|
outportb (0x64, 0xfe);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void eoi()
|
//Halts (freezes) the computer
|
||||||
|
inline void halt()
|
||||||
{
|
{
|
||||||
outportb(0x20, 0x20); //EOI
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Signals an End Of Interrupt signal to both the second and first PIC unit
|
||||||
inline void eoi2()
|
inline void eoi2()
|
||||||
{
|
{
|
||||||
outportb(0xA0, 0x20);
|
outportb(0xA0, 0x20);
|
||||||
outportb(0x20, 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+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_FAT_SEG 0x07E0 ;right after boot sector
|
||||||
%define BOOT_ROOT_SEG 0x0900 ;right after FAT
|
%define BOOT_ROOT_SEG 0x0900 ;right after FAT
|
||||||
%define BOOT_KERNEL_SEG 0x0AC0 ;right after ROOT_DIR
|
%define BOOT_KERNEL_SEG 0x0AC0 ;right after ROOT_DIR
|
||||||
%define BOOT_STAGE2_SEG 0x0B00 ;right after KERNEL_SEG
|
%define BOOT_STAGE2_SEG 0x0B00 ;right after KERNEL_SEG
|
||||||
%define BOOT_STAGE2_ADD 0xB000 ;address of stage2 to jump to, org at
|
%define BOOT_STAGE2_ADD 0xB000 ;address of stage2 to jump to, org at
|
||||||
%define BOOT_KERNEL_ADD 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_RD_ADD 0x200000 ;2mb for ram disk
|
||||||
|
|
||||||
%define BOOT_DATA_SEG 0x9000 ;data gathered by stage2 loader goes here
|
%define BOOT_DATA_SEG 0x9000 ;data gathered by stage2 loader goes here
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
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
|
||||||
@@ -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);
|
||||||
|
|
||||||
|
|
||||||
+27
-5
@@ -1,22 +1,44 @@
|
|||||||
//functions.h
|
//functions.h
|
||||||
//05/07/03 Josh Holtrop
|
//05/07/03 Josh Holtrop
|
||||||
//for HOS
|
//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 outportb(unsigned int port, unsigned char value);
|
||||||
inline void outportw(unsigned int port, unsigned int value);
|
inline void outportw(unsigned int port, unsigned int value);
|
||||||
inline byte inportb(unsigned short port);
|
inline byte inportb(unsigned short port);
|
||||||
void enable_ints();
|
inline void enable_ints();
|
||||||
void disable_ints();
|
inline void disable_ints();
|
||||||
inline void restart();
|
inline void restart();
|
||||||
|
inline void halt();
|
||||||
void remap_pics(int pic1, int pic2);
|
void remap_pics(int pic1, int pic2);
|
||||||
inline void pic1_mask(byte mask);
|
inline void pic1_mask(byte mask);
|
||||||
inline void pic2_mask(byte mask);
|
inline void pic2_mask(byte mask);
|
||||||
inline void eoi();
|
inline void eoi();
|
||||||
inline void eoi2();
|
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:
|
gdtr:
|
||||||
dw gdt_end-gdt-1
|
dw gdt_end-gdt-1
|
||||||
dd GDT
|
dd GDT_P
|
||||||
gdt:
|
gdt:
|
||||||
dd 0
|
dd 0
|
||||||
dd 0
|
dd 0
|
||||||
|
|||||||
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:
|
idtr:
|
||||||
dw 50*8-1 ;size of idt
|
dw 50*8-1 ;size of idt
|
||||||
dd IDT ;address of idt
|
dd IDT_V ;address of idt
|
||||||
|
|
||||||
|
|
||||||
%macro isr_label 1
|
%macro isr_label 1
|
||||||
isr_%1:
|
isr_%1:
|
||||||
|
push eax
|
||||||
mov eax, %1
|
mov eax, %1
|
||||||
jmp isr_main
|
jmp isr_main
|
||||||
%endmacro
|
%endmacro
|
||||||
@@ -62,6 +67,9 @@ isr_label 48
|
|||||||
isr_label 49
|
isr_label 49
|
||||||
|
|
||||||
isr_main:
|
isr_main:
|
||||||
|
cmp eax, 0x30
|
||||||
|
jz isr_syscall
|
||||||
|
|
||||||
pusha
|
pusha
|
||||||
push ds
|
push ds
|
||||||
push es
|
push es
|
||||||
@@ -75,10 +83,27 @@ isr_main:
|
|||||||
pop es
|
pop es
|
||||||
pop ds
|
pop ds
|
||||||
popa
|
popa
|
||||||
|
pop eax
|
||||||
|
|
||||||
iret
|
iret
|
||||||
|
|
||||||
|
|
||||||
|
isr_syscall:
|
||||||
|
pop eax ;syscall function number
|
||||||
|
pusha
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
|
||||||
|
push ebx
|
||||||
|
call _putc
|
||||||
|
add esp, 4
|
||||||
|
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
popa
|
||||||
|
iret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -1,5 +1,6 @@
|
|||||||
//k_defines.h
|
//k_defines.h
|
||||||
//03/17/03 Josh Holtrop
|
//03/17/03 Josh Holtrop
|
||||||
|
//Modified: 10/30/03
|
||||||
|
|
||||||
#define PIC1 0x20
|
#define PIC1 0x20
|
||||||
#define PIC2 0xA0
|
#define PIC2 0xA0
|
||||||
@@ -28,9 +29,12 @@
|
|||||||
#define YELLOW_TXT 0x0E
|
#define YELLOW_TXT 0x0E
|
||||||
#define BRWHITE_TXT 0x0F
|
#define BRWHITE_TXT 0x0F
|
||||||
|
|
||||||
#define FREERAM_START 0x268000
|
#define FREERAM_START 0x368000 // 0x368000 is first available byte (this is right after the initrd @ 2mb, 1440kb.
|
||||||
|
#define MAX_RAM 0x40000000 //1gb maximum RAM supported
|
||||||
|
|
||||||
#define KERNEL_PID 0x02
|
#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 char byte;
|
||||||
typedef unsigned short word;
|
typedef unsigned short word;
|
||||||
|
|||||||
+49
-10
@@ -1,18 +1,56 @@
|
|||||||
|
;kernel.asm
|
||||||
|
;Author: Josh Holtrop
|
||||||
|
;Modified: 10/30/03
|
||||||
|
|
||||||
%include "bootdef.inc"
|
%define GDT_P 0x100000; ;1mb physical - Global Descriptor Table space
|
||||||
|
%define GDT_V GDT_P+0xC0000000
|
||||||
%define GDT 0x140000
|
%define IDT_P 0x102000 ;1mb+8kb - Interrupt Descriptor Table space
|
||||||
%define IDT 0x150000
|
%define IDT_V IDT_P+0xC0000000
|
||||||
|
%define PDBR_P 0x104000 ;1mb+16kb - Page Directory Base Register (first PD)
|
||||||
|
%define PDBR_V PDBR_P+0xC0000000
|
||||||
|
%define LOPT_P 0x105000 ;1mb+20kb - LOw Page Table for mapping first 4mb
|
||||||
|
%define LOPT_V LOPT_P+0xC0000000
|
||||||
|
%define KERNEL_P 0x106000 ;1mb+24kb - the kernel's physical address
|
||||||
|
%define KERNEL_V KERNEL_P+0xC0000000 ;3gb+1mb+24kb, the virtual address of the kernel
|
||||||
|
|
||||||
[global start]
|
[global start]
|
||||||
[extern _isr]
|
[extern _isr]
|
||||||
[extern _k_init]
|
[extern _k_init]
|
||||||
|
[extern _putc]
|
||||||
|
|
||||||
bits 32
|
bits 32
|
||||||
|
|
||||||
|
;This is where the kernel begins execution
|
||||||
|
;At this point, the temporary gdt is set up to "map" 0xC000_0000 to 0x0.
|
||||||
|
;We must enable paging with the first 4mb mapped 1:1 virtual:physical
|
||||||
|
; and with the 4mb starting at 0xC000_0000 mapped to the first 4mb physical.
|
||||||
|
;Then we can start using our "real" gdt, then unmap the lower 4mb.
|
||||||
start:
|
start:
|
||||||
cli ;if they weren't already off
|
cli ;if they weren't already off
|
||||||
mov edi, GDT
|
|
||||||
|
xor eax, eax
|
||||||
|
mov edi, PDBR_V
|
||||||
|
mov ecx, 1024 ;clear the PDBR
|
||||||
|
rep stosd
|
||||||
|
mov [PDBR_V], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table (read/write, present)
|
||||||
|
mov [PDBR_V+0xC00], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table (read/write, present)
|
||||||
|
|
||||||
|
mov edi, LOPT_V
|
||||||
|
mov ecx, 1024
|
||||||
|
mov eax, 0x03 ;starting physical address = 0x0 (read/write, present flags)
|
||||||
|
fill_lopt_loop: ;fill the page table
|
||||||
|
stosd
|
||||||
|
add eax, 4096 ;increment next phsyical address by 4kb
|
||||||
|
loop fill_lopt_loop
|
||||||
|
|
||||||
|
mov eax, PDBR_P
|
||||||
|
mov cr3, eax ;store the Page Directory Base Address
|
||||||
|
mov eax, cr0
|
||||||
|
or eax, 0x80000000 ;set page enable bit
|
||||||
|
mov cr0, eax ;now paging is active!
|
||||||
|
|
||||||
|
|
||||||
|
mov edi, GDT_V
|
||||||
mov esi, gdt
|
mov esi, gdt
|
||||||
mov ecx, gdt_end-gdt
|
mov ecx, gdt_end-gdt
|
||||||
copy_gdt:
|
copy_gdt:
|
||||||
@@ -20,7 +58,7 @@ copy_gdt:
|
|||||||
stosb
|
stosb
|
||||||
loop copy_gdt
|
loop copy_gdt
|
||||||
|
|
||||||
mov edi, IDT ;destination
|
mov edi, IDT_V ;destination
|
||||||
mov esi, isr_0 ;address of isr0
|
mov esi, isr_0 ;address of isr0
|
||||||
mov edx, isr_1-isr_0 ;distance between isr labels
|
mov edx, isr_1-isr_0 ;distance between isr labels
|
||||||
mov ecx, 50 ;number of isrlabels
|
mov ecx, 50 ;number of isrlabels
|
||||||
@@ -38,6 +76,7 @@ fill_idt:
|
|||||||
mov esi, ebx
|
mov esi, ebx
|
||||||
add esi, edx
|
add esi, edx
|
||||||
loop fill_idt
|
loop fill_idt
|
||||||
|
mov word [IDT_V+0x30*8+4], 0xEE00 ;interrupt 0x30 has user priviledges
|
||||||
|
|
||||||
lgdt [gdtr] ;load gdt
|
lgdt [gdtr] ;load gdt
|
||||||
jmp KERNEL_CODE:newgdtcontinue
|
jmp KERNEL_CODE:newgdtcontinue
|
||||||
@@ -48,15 +87,15 @@ newgdtcontinue:
|
|||||||
mov gs, ax
|
mov gs, ax
|
||||||
mov fs, ax
|
mov fs, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
mov esp, 0x1ffffc ;stack just under 2mb, moves downward
|
mov esp, 0xc01ffffc ;stack just under 3gb+2mb, moves downward
|
||||||
lidt [idtr] ;load idt
|
lidt [idtr] ;load idt
|
||||||
|
|
||||||
call _k_init
|
call _k_init
|
||||||
|
haltit:
|
||||||
hlt ;halt processor when k_init is done
|
hlt ;halt processor when k_init is done
|
||||||
jmp $ ;shouldn't get here...
|
jmp haltit ;shouldn't get here...
|
||||||
|
|
||||||
%include "gdt.inc"
|
%include "gdt.inc"
|
||||||
%include "idt.inc"
|
%include "idt.inc"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,93 +1,127 @@
|
|||||||
//kernel.c
|
//kernel.c
|
||||||
//08/13/03 Josh Holtrop
|
//08/13/03 Josh Holtrop
|
||||||
//Holtrop's Operating System
|
//Holtrop's Operating System
|
||||||
|
//Version: 0.12
|
||||||
|
//Modified: 12/30/03
|
||||||
|
|
||||||
#define VXR video_mode.XResolution
|
#include "k_defines.h" //#DEFINE's for kernel
|
||||||
#define VYR video_mode.YResolution
|
|
||||||
|
|
||||||
#include "k_defines.h"
|
|
||||||
|
|
||||||
#include "lib/string.h"
|
#include "functions.h" //general functions
|
||||||
#include "lib/io.h"
|
#include "video.h" //video functions
|
||||||
|
#include "mm.h" //physical memory management functions
|
||||||
#include "functions.h"
|
#include "vmm.h" //virtual memory management & paging functions
|
||||||
#include "video.h"
|
#include "keyboard.h" //generic keyboard driver & functions
|
||||||
#include "mm.h"
|
#include "mouse.h" //generic ps/2 mouse driver & functions
|
||||||
#include "keyboard.h"
|
#include "fdc.h" //Floppy Disk Controller functions
|
||||||
#include "mouse.h"
|
#include "stdfont.h" //Standard font bitmask array
|
||||||
|
#include "kio.h"
|
||||||
|
#include "vfs.h"
|
||||||
|
#include "rd.h"
|
||||||
|
#include "fat12.h"
|
||||||
|
|
||||||
void isr(dword num);
|
void isr(dword num);
|
||||||
void k_init();
|
void k_init();
|
||||||
|
|
||||||
|
/* These functions are defined in asmfuncs.asm */
|
||||||
|
extern dword write_cr0(dword cr0);
|
||||||
|
extern dword 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 "mouse.c"
|
||||||
#include "keyboard.c"
|
#include "keyboard.c"
|
||||||
#include "mm.c"
|
#include "mm.c"
|
||||||
|
#include "vmm.c"
|
||||||
#include "functions.c"
|
#include "functions.c"
|
||||||
#include "video.c"
|
#include "video.c"
|
||||||
|
|
||||||
dword timer = 0;
|
dword timer = 0;
|
||||||
|
|
||||||
|
//Main kernel initialization method
|
||||||
void k_init()
|
void k_init()
|
||||||
{
|
{
|
||||||
|
// ===== Initialization
|
||||||
|
fdc_sendDOR(0x0C); //turn off floppy motor!!
|
||||||
console_cls();
|
console_cls();
|
||||||
remap_pics(0x20, 0x28);
|
video_init();
|
||||||
//set timer : 2e9c = 100hz
|
|
||||||
outportb(0x43, 0x34);
|
|
||||||
outportb(0x40, 0x9c); //lsb
|
|
||||||
outportb(0x40, 0x2e); //msb
|
|
||||||
video_init((ModeInfoBlock *) 0x90306);
|
|
||||||
video_rectf(VXR*3/11, 0, VXR*4/11, VYR-1, 0x00000088); //test rectangles, draws "HOS"
|
|
||||||
video_rectf(VXR*7/11, 0, VXR*8/11, VYR-1, 0x00000088);
|
|
||||||
video_rectf(VXR/11, 0, VXR*2/11, VYR*2/5, 0x00000088);
|
|
||||||
video_rectf(VXR/11, VYR*3/5, VXR*2/11, VYR-1, 0x00000088);
|
|
||||||
video_rectf(VXR*5/11, VYR/5, VXR*6/11, VYR*4/5, 0x00000088);
|
|
||||||
video_rectf(VXR*9/11, VYR/5, VXR-1, VYR*2/5, 0x00000088);
|
|
||||||
video_rectf(VXR*8/11, VYR*3/5, VXR*10/11, VYR*4/5, 0x00000088);
|
|
||||||
|
|
||||||
video_vert(10, 10, 16, 0x00ffff00); //should be yellow 'H'
|
|
||||||
video_horiz(13, 10, 14, 0x00ffff00);
|
|
||||||
video_vert(14, 10, 16, 0x00ffff00);
|
|
||||||
|
|
||||||
video_horiz(10, 17, 21, 0x00ffff00);
|
|
||||||
video_vert(19, 10, 16, 0x00ffff00);
|
|
||||||
video_horiz(16, 17, 21, 0x00ffff00);
|
|
||||||
|
|
||||||
int a, b;
|
|
||||||
for (a = 0; a < 256; a++)
|
|
||||||
{
|
|
||||||
for (b = 0; b < 256; b++)
|
|
||||||
{
|
|
||||||
video_pset(a+5, b+30, (a<<16)|(b<<8));
|
|
||||||
video_pset(a+270, b+30, (a<<8)|(b));
|
|
||||||
video_pset(a+535, b+30, (a<<16)|(b));
|
|
||||||
|
|
||||||
video_pset(a+5, b+290, (a<<16)|(b<<8)|0x000000ff);
|
|
||||||
video_pset(a+270, b+290, (a<<8)|(b)|0x00ff0000);
|
|
||||||
video_pset(a+535, b+290, (a<<16)|(b)|0x0000ff00);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mm_init();
|
mm_init();
|
||||||
|
vmm_init();
|
||||||
|
remap_pics(0x20, 0x28);
|
||||||
|
init_timer();
|
||||||
mouse_init();
|
mouse_init();
|
||||||
enable_ints();
|
|
||||||
printf("Memory available to OS: %d MB (Bytes: %d)\n", mm_totalmem/0x100000, mm_totalmem);
|
|
||||||
pic1_mask(0); //unmask IRQ's 0-7
|
pic1_mask(0); //unmask IRQ's 0-7
|
||||||
pic2_mask(0); //unmask IRQ's 8-15
|
pic2_mask(0); //unmask IRQ's 8-15
|
||||||
|
vfs_init();
|
||||||
|
enable_ints();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
dword key = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
key = kbdWaitKey();
|
key = kbdWaitKey();
|
||||||
putc(key);
|
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)
|
void isr(dword num)
|
||||||
{
|
{
|
||||||
switch(num)
|
switch(num)
|
||||||
{
|
{
|
||||||
|
case 14:
|
||||||
|
printf("Page fault, CR2 = 0x%x\n", read_cr2());
|
||||||
|
halt();
|
||||||
|
break;
|
||||||
case 0x20: // IRQ0 - timer interrupt
|
case 0x20: // IRQ0 - timer interrupt
|
||||||
timer++;
|
timer++;
|
||||||
(*(byte *)0xb8000)++;
|
(*(byte *)(0xc00b8000))++;
|
||||||
eoi();
|
eoi();
|
||||||
break;
|
break;
|
||||||
case 0x21: // IRQ1 - keyboard interrupt
|
case 0x21: // IRQ1 - keyboard interrupt
|
||||||
@@ -99,6 +133,7 @@ void isr(dword num)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Interrupt %d (0x%x) Unhandled!!\n", num, num);
|
printf("Interrupt %d (0x%x) Unhandled!!\n", num, num);
|
||||||
|
halt();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-25
@@ -1,28 +1,29 @@
|
|||||||
//Keyboard.c
|
//Keyboard.c
|
||||||
// Created: 04/17/03 Josh Holtrop
|
// Created: 04/17/03 Josh Holtrop
|
||||||
// Modified: 09/09/03
|
// Modified: 10/30/03
|
||||||
//for HOS
|
//for HOS
|
||||||
|
|
||||||
#define KBD_BUFFER_LENGTH 64
|
#define KBD_BUFFER_LENGTH 64
|
||||||
|
|
||||||
byte kbdFlags = 0;
|
byte kbdFlags = 0; //holds current keyboard flags - caps/num/scroll/shift/ctrl/alt
|
||||||
byte kbdAscii = 0;
|
byte kbdAscii = 0; //holds ASCII value of a key pressed
|
||||||
byte kbdScan = 0;
|
byte kbdScan = 0; //holds the keyboard scan code of a key pressed
|
||||||
|
|
||||||
dword kbdBuffer[KBD_BUFFER_LENGTH];
|
dword kbdBuffer[KBD_BUFFER_LENGTH]; //a buffer for all keypresses
|
||||||
int kbdBufferStart = 0;
|
int kbdBufferStart = 0; //position of next key in buffer
|
||||||
int kbdBufferLen = 0;
|
int kbdBufferLen = 0; //number of keys left in the buffer
|
||||||
byte kbdExt = 0;
|
byte kbdExt = 0; //# of extended key codes left to input
|
||||||
byte kbdExt2 = 0;
|
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)
|
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....
|
//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 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";
|
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:
|
//====FUNCTIONS:
|
||||||
|
// The Keyboard Interrupt Service Routine
|
||||||
void isr_keyboard()
|
void isr_keyboard()
|
||||||
{
|
{
|
||||||
kbdScan = inportb(0x60);
|
kbdScan = inportb(0x60);
|
||||||
@@ -35,20 +36,20 @@ void isr_keyboard()
|
|||||||
|
|
||||||
if (kbdScan == 0xFA) //250 //ACKnowledge
|
if (kbdScan == 0xFA) //250 //ACKnowledge
|
||||||
{
|
{
|
||||||
|
//printf("KBD_ACK 0x%x!\n", ackReason);
|
||||||
if (ackReason == 0xED) //reset LEDs
|
if (ackReason == 0xED) //reset LEDs
|
||||||
{
|
{
|
||||||
outportb(0x64, (kbdFlags & 0x07));
|
outportb(0x60, (kbdFlags & 0x07));
|
||||||
printf("KBD_ACK!");
|
|
||||||
}
|
}
|
||||||
ackReason = 0;
|
ackReason = 0;
|
||||||
}
|
}
|
||||||
if (kbdScan == 224) //extended key
|
if (kbdScan == 224) //extended key
|
||||||
{
|
{
|
||||||
kbdExt = 1;
|
kbdExt = 1;
|
||||||
eoi();
|
eoi();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (kbdScan == 225)
|
if (kbdScan == 225) //2nd-set-extended key
|
||||||
{
|
{
|
||||||
kbdExt2 = 2;
|
kbdExt2 = 2;
|
||||||
eoi();
|
eoi();
|
||||||
@@ -57,7 +58,7 @@ void isr_keyboard()
|
|||||||
|
|
||||||
//====handle control keys::
|
//====handle control keys::
|
||||||
kbdAscii = 2;
|
kbdAscii = 2;
|
||||||
switch (kbdScan) //control keys
|
switch (kbdScan) //control keys
|
||||||
{
|
{
|
||||||
case KBD_SCAN_LSHIFT:
|
case KBD_SCAN_LSHIFT:
|
||||||
kbdFlags |= KBD_SHIFT;
|
kbdFlags |= KBD_SHIFT;
|
||||||
@@ -96,17 +97,17 @@ void isr_keyboard()
|
|||||||
case KBD_SCAN_CAPS+KBD_SCAN_RELEASED:
|
case KBD_SCAN_CAPS+KBD_SCAN_RELEASED:
|
||||||
kbdFlags ^= KBD_CAPS;
|
kbdFlags ^= KBD_CAPS;
|
||||||
kbdAscii = 1;
|
kbdAscii = 1;
|
||||||
kbd_resetLEDs(); //update LEDs
|
kbd_resetLEDs(); //update LEDs
|
||||||
break;
|
break;
|
||||||
case KBD_SCAN_SCROLL+KBD_SCAN_RELEASED:
|
case KBD_SCAN_SCROLL+KBD_SCAN_RELEASED:
|
||||||
kbdFlags ^= KBD_SCROLL;
|
kbdFlags ^= KBD_SCROLL;
|
||||||
kbdAscii = 1;
|
kbdAscii = 1;
|
||||||
kbd_resetLEDs(); //update LEDs
|
kbd_resetLEDs(); //update LEDs
|
||||||
break;
|
break;
|
||||||
case KBD_SCAN_NUM+KBD_SCAN_RELEASED:
|
case KBD_SCAN_NUM+KBD_SCAN_RELEASED:
|
||||||
kbdFlags ^= KBD_NUM;
|
kbdFlags ^= KBD_NUM;
|
||||||
kbdAscii = 1;
|
kbdAscii = 1;
|
||||||
kbd_resetLEDs(); //update LEDs
|
kbd_resetLEDs(); //update LEDs
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (kbdAscii == 1)
|
if (kbdAscii == 1)
|
||||||
@@ -170,7 +171,8 @@ void isr_keyboard()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//====do something with key::
|
//====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.");
|
printf("Initiating reboot.");
|
||||||
restart();
|
restart();
|
||||||
@@ -196,19 +198,19 @@ void isr_keyboard()
|
|||||||
|
|
||||||
eoi();
|
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'))
|
if ((asciiCode >= 'A') & (asciiCode <= 'Z'))
|
||||||
return (asciiCode + ('a' - 'A'));
|
return (asciiCode + ('a' - 'A'));
|
||||||
if ((asciiCode >= 'a') & (asciiCode <= 'z'))
|
if ((asciiCode >= 'a') & (asciiCode <= 'z'))
|
||||||
return (asciiCode - ('a' - 'A'));
|
return (asciiCode - ('a' - 'A'));
|
||||||
return asciiCode;
|
return asciiCode;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
//Gets a key from the buffer, returns 0 if no keys available, returns immediately
|
||||||
dword kbdGetKey()
|
dword kbdGetKey()
|
||||||
{
|
{
|
||||||
if (kbdBufferLen == 0) //buffer empty
|
if (kbdBufferLen == 0) //buffer empty
|
||||||
@@ -221,6 +223,7 @@ dword kbdGetKey()
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Gets a key from the buffer, if no keys available, waits for one to be entered
|
||||||
dword kbdWaitKey()
|
dword kbdWaitKey()
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
@@ -236,10 +239,11 @@ dword kbdWaitKey()
|
|||||||
return retVal;
|
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()
|
inline void kbd_resetLEDs()
|
||||||
{
|
{
|
||||||
outportb(0x64, 0xED);
|
outportb(0x60, 0xED);
|
||||||
//outportb(0x64, (kbdFlags & 0x07));
|
//outportb(0x60, (kbdFlags & 0x07));
|
||||||
ackReason = 0xED;
|
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
|
||||||
|
|
||||||
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
|
|
||||||
typedef unsigned int dword;
|
|
||||||
typedef unsigned short word;
|
|
||||||
typedef unsigned char byte;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-532
@@ -1,532 +0,0 @@
|
|||||||
|
|
||||||
%macro jzfar 1
|
|
||||||
jnz %%skip
|
|
||||||
jmp %1
|
|
||||||
%%skip:
|
|
||||||
|
|
||||||
%endmacro
|
|
||||||
|
|
||||||
[global _writeCursorPosition]
|
|
||||||
[global _getCursorPosition]
|
|
||||||
[global _putc]
|
|
||||||
[global _puts]
|
|
||||||
[global _printf]
|
|
||||||
[global _console_scroll]
|
|
||||||
[global _console_cls]
|
|
||||||
[global _putHex]
|
|
||||||
[global _putDec]
|
|
||||||
[global _putDecu]
|
|
||||||
|
|
||||||
|
|
||||||
;
|
|
||||||
;void writeCursorPosition(word pos)
|
|
||||||
;
|
|
||||||
_writeCursorPosition:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
|
|
||||||
push eax
|
|
||||||
push ebx
|
|
||||||
push edx
|
|
||||||
|
|
||||||
mov eax, [ebp+8] ;cursor position in ax
|
|
||||||
|
|
||||||
mov bl, al
|
|
||||||
mov dx, 0x03D4
|
|
||||||
mov al, 0x0E
|
|
||||||
out dx, al
|
|
||||||
|
|
||||||
inc dx
|
|
||||||
mov al, ah
|
|
||||||
out dx, al
|
|
||||||
|
|
||||||
dec dx
|
|
||||||
mov al, 0x0F
|
|
||||||
out dx, al
|
|
||||||
|
|
||||||
inc dx
|
|
||||||
mov al, bl
|
|
||||||
out dx, al
|
|
||||||
|
|
||||||
pop edx
|
|
||||||
pop ebx
|
|
||||||
pop eax
|
|
||||||
pop ebp
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
;
|
|
||||||
;word getCursorPosition()
|
|
||||||
;
|
|
||||||
_getCursorPosition:
|
|
||||||
push ebx
|
|
||||||
push edx
|
|
||||||
|
|
||||||
xor eax, eax
|
|
||||||
mov dx, 0x03D4
|
|
||||||
mov al, 0x0E
|
|
||||||
out dx, al
|
|
||||||
|
|
||||||
inc dx
|
|
||||||
in al, dx
|
|
||||||
mov bl, al
|
|
||||||
|
|
||||||
dec dx
|
|
||||||
mov al, 0x0F
|
|
||||||
out dx, al
|
|
||||||
|
|
||||||
inc dx
|
|
||||||
in al, dx
|
|
||||||
mov ah, bl
|
|
||||||
|
|
||||||
pop edx
|
|
||||||
pop ebx
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
;
|
|
||||||
;int putc(int chr)
|
|
||||||
;
|
|
||||||
_putc:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
push ebx
|
|
||||||
push ecx
|
|
||||||
push edx
|
|
||||||
|
|
||||||
call _getCursorPosition
|
|
||||||
mov ebx, eax
|
|
||||||
mov ecx, ebx
|
|
||||||
|
|
||||||
mov eax, [ebp+8] ;al=character
|
|
||||||
cmp al, 10 ;newline
|
|
||||||
jz putc_newline
|
|
||||||
cmp al, 9 ;tab
|
|
||||||
jz putc_tab
|
|
||||||
|
|
||||||
shl ebx, 1
|
|
||||||
add ebx, 0xb8000
|
|
||||||
mov ah, 0x07
|
|
||||||
mov [ebx], ax
|
|
||||||
mov eax, ecx
|
|
||||||
inc eax
|
|
||||||
cmp eax, 2000
|
|
||||||
jnz putc_writeit2
|
|
||||||
call _console_scroll
|
|
||||||
mov eax, 2000-80
|
|
||||||
putc_writeit2:
|
|
||||||
push eax
|
|
||||||
call _writeCursorPosition
|
|
||||||
add esp, 4
|
|
||||||
jmp putc_done
|
|
||||||
|
|
||||||
putc_newline:
|
|
||||||
mov eax, ebx ;eax = cursor position
|
|
||||||
mov ebx, 80
|
|
||||||
xor edx, edx
|
|
||||||
div bx ;ax=dx:ax/bx, dx=remainder
|
|
||||||
mov bx, 80
|
|
||||||
sub bx, dx
|
|
||||||
mov eax, ecx
|
|
||||||
add eax, ebx ;eax = new cursor position
|
|
||||||
cmp eax, 2000
|
|
||||||
jnz putc_newline_writeit2
|
|
||||||
call _console_scroll
|
|
||||||
mov eax, 2000-80 ;beginning of last row
|
|
||||||
putc_newline_writeit2:
|
|
||||||
push eax
|
|
||||||
call _writeCursorPosition
|
|
||||||
add esp, 4
|
|
||||||
jmp putc_done
|
|
||||||
|
|
||||||
putc_tab:
|
|
||||||
mov eax, ebx ;eax = cursor position
|
|
||||||
mov ebx, 8
|
|
||||||
div bl ;al=ax/bl, ah=remainder
|
|
||||||
xor edx, edx
|
|
||||||
mov dl, ah
|
|
||||||
mov bx, 8
|
|
||||||
sub bx, dx
|
|
||||||
mov eax, ecx
|
|
||||||
add eax, ebx ;eax = new cursor position
|
|
||||||
cmp eax, 2000
|
|
||||||
jnz putc_tab_writeit2
|
|
||||||
call _console_scroll
|
|
||||||
mov eax, 2000-80 ;beginning of last row
|
|
||||||
putc_tab_writeit2:
|
|
||||||
push eax
|
|
||||||
call _writeCursorPosition
|
|
||||||
add esp, 4
|
|
||||||
|
|
||||||
putc_done:
|
|
||||||
pop edx
|
|
||||||
pop ecx
|
|
||||||
pop ebx
|
|
||||||
pop ebp
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;
|
|
||||||
;void printf(char *fmt, ... )
|
|
||||||
;
|
|
||||||
_printf:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
pusha
|
|
||||||
mov ebx, [ebp+8] ;ebx = position in format string
|
|
||||||
mov esi, ebp
|
|
||||||
add esi, 12 ;esi = to next variable arg
|
|
||||||
xor ecx, ecx ;ecx used if we encounter a '%'
|
|
||||||
printf_loop:
|
|
||||||
mov al, [ebx]
|
|
||||||
inc ebx
|
|
||||||
cmp al, 0
|
|
||||||
jzfar printf_done
|
|
||||||
cmp ecx, 1
|
|
||||||
jz printf_special
|
|
||||||
cmp al, '%'
|
|
||||||
jzfar printf_percent
|
|
||||||
|
|
||||||
push eax
|
|
||||||
call _putc
|
|
||||||
add esp, 4
|
|
||||||
jmp printf_loop
|
|
||||||
|
|
||||||
printf_special:
|
|
||||||
xor ecx, ecx
|
|
||||||
cmp al, 'd'
|
|
||||||
jz printf_decimal
|
|
||||||
cmp al, 'u'
|
|
||||||
jz printf_decimalu
|
|
||||||
cmp al, 'x'
|
|
||||||
jz printf_hex
|
|
||||||
cmp al, '%'
|
|
||||||
jz printf_ppercent
|
|
||||||
cmp al, 's'
|
|
||||||
jz printf_string
|
|
||||||
cmp al, 'c'
|
|
||||||
jz printf_char
|
|
||||||
jmp printf_special_done
|
|
||||||
|
|
||||||
printf_decimal:
|
|
||||||
mov eax, [esi]
|
|
||||||
push eax
|
|
||||||
call _putDec
|
|
||||||
add esp, 4
|
|
||||||
jmp printf_special_done
|
|
||||||
|
|
||||||
printf_decimalu:
|
|
||||||
mov eax, [esi]
|
|
||||||
push eax
|
|
||||||
call _putDecu
|
|
||||||
add esp, 4
|
|
||||||
jmp printf_special_done
|
|
||||||
|
|
||||||
printf_hex:
|
|
||||||
mov eax, [esi]
|
|
||||||
push eax
|
|
||||||
call _putHex
|
|
||||||
add esp, 4
|
|
||||||
jmp printf_special_done
|
|
||||||
|
|
||||||
printf_ppercent:
|
|
||||||
push eax
|
|
||||||
call _putc
|
|
||||||
add esp, 4
|
|
||||||
jmp printf_special_done
|
|
||||||
|
|
||||||
printf_string:
|
|
||||||
mov eax, [esi]
|
|
||||||
push eax
|
|
||||||
call _puts
|
|
||||||
add esp, 4
|
|
||||||
jmp printf_special_done
|
|
||||||
|
|
||||||
printf_char:
|
|
||||||
mov eax, [esi]
|
|
||||||
push eax
|
|
||||||
call _putc
|
|
||||||
add esp, 4
|
|
||||||
jmp printf_special_done
|
|
||||||
|
|
||||||
printf_special_done
|
|
||||||
add esi, 4 ;point to next extra argument
|
|
||||||
jmp printf_loop
|
|
||||||
|
|
||||||
printf_percent:
|
|
||||||
mov ecx, 1
|
|
||||||
jmp printf_loop
|
|
||||||
|
|
||||||
|
|
||||||
printf_done:
|
|
||||||
popa
|
|
||||||
pop ebp
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;
|
|
||||||
;void console_scroll()
|
|
||||||
;
|
|
||||||
_console_scroll:
|
|
||||||
pusha
|
|
||||||
mov esi, 0xb8000+160
|
|
||||||
mov edi, 0xb8000
|
|
||||||
mov ecx, 960 ;(2000-80)/2
|
|
||||||
console_scroll_loop:
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
loop console_scroll_loop
|
|
||||||
mov ax, 0x0720
|
|
||||||
mov ecx, 80
|
|
||||||
console_scroll_loop2:
|
|
||||||
stosw
|
|
||||||
loop console_scroll_loop2
|
|
||||||
popa
|
|
||||||
ret
|
|
||||||
|
|
||||||
;
|
|
||||||
;void console_cls()
|
|
||||||
;
|
|
||||||
_console_cls:
|
|
||||||
pusha
|
|
||||||
mov edi, 0xb8000
|
|
||||||
mov ax, 0x0720
|
|
||||||
mov ecx, 2000
|
|
||||||
console_cls_loop:
|
|
||||||
stosw
|
|
||||||
loop console_cls_loop
|
|
||||||
push dword 0
|
|
||||||
call _writeCursorPosition
|
|
||||||
add esp, 4
|
|
||||||
popa
|
|
||||||
ret
|
|
||||||
|
|
||||||
;
|
|
||||||
;int putHex(dword number)
|
|
||||||
;
|
|
||||||
_putHex:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
pusha
|
|
||||||
mov eax, [ebp+8] ;eax = number to print
|
|
||||||
xor ebx, ebx ;we have not printed a character yet
|
|
||||||
mov ecx, 8 ;counter for number of characters
|
|
||||||
|
|
||||||
putHex_loop:
|
|
||||||
push eax
|
|
||||||
push ecx
|
|
||||||
|
|
||||||
dec ecx
|
|
||||||
shl ecx, 2 ;edx=counter*4 (amount to shift by)
|
|
||||||
shr eax, cl
|
|
||||||
and eax, 0x0F
|
|
||||||
cmp cl, 0
|
|
||||||
jz putHex_notzero ;if number is 0
|
|
||||||
cmp al, 0
|
|
||||||
jnz putHex_notzero
|
|
||||||
cmp bl, 0
|
|
||||||
jz putHex_loop_end
|
|
||||||
putHex_notzero:
|
|
||||||
mov bl, 1
|
|
||||||
add eax, '0'
|
|
||||||
cmp eax, '9'
|
|
||||||
jbe putHex_dontadjust
|
|
||||||
add eax, 'A'-'9'-1
|
|
||||||
putHex_dontadjust:
|
|
||||||
push eax
|
|
||||||
call _putc
|
|
||||||
add esp, 4
|
|
||||||
|
|
||||||
putHex_loop_end:
|
|
||||||
pop ecx
|
|
||||||
pop eax
|
|
||||||
loop putHex_loop
|
|
||||||
|
|
||||||
popa
|
|
||||||
pop ebp
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
;
|
|
||||||
;int puts(char *str)
|
|
||||||
;
|
|
||||||
_puts:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
push esi
|
|
||||||
push eax
|
|
||||||
mov esi, [ebp+8] ;esi = to string
|
|
||||||
puts_loop:
|
|
||||||
lodsb
|
|
||||||
cmp al, 0
|
|
||||||
jz puts_done
|
|
||||||
push eax
|
|
||||||
call _putc
|
|
||||||
add esp, 4
|
|
||||||
jmp puts_loop
|
|
||||||
|
|
||||||
puts_done:
|
|
||||||
pop eax
|
|
||||||
pop esi
|
|
||||||
pop ebp
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_putDecu:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
sub esp, 24
|
|
||||||
mov DWORD [ebp-4], 1
|
|
||||||
mov BYTE [ebp-5], 0
|
|
||||||
L2:
|
|
||||||
mov edx, DWORD [ebp+8]
|
|
||||||
mov eax, -858993459
|
|
||||||
mul edx
|
|
||||||
mov eax, edx
|
|
||||||
shr eax, 3
|
|
||||||
cmp eax, DWORD [ebp-4]
|
|
||||||
jae L4
|
|
||||||
jmp L3
|
|
||||||
L4:
|
|
||||||
mov eax, DWORD [ebp-4]
|
|
||||||
mov edx, eax
|
|
||||||
sal edx, 2
|
|
||||||
add edx, eax
|
|
||||||
lea eax, [edx+edx]
|
|
||||||
mov DWORD [ebp-4], eax
|
|
||||||
jmp L2
|
|
||||||
L3:
|
|
||||||
nop
|
|
||||||
L5:
|
|
||||||
cmp DWORD [ebp-4], 1
|
|
||||||
ja L7
|
|
||||||
jmp L6
|
|
||||||
L7:
|
|
||||||
mov edx, DWORD [ebp+8]
|
|
||||||
mov eax, edx
|
|
||||||
mov edx, 0
|
|
||||||
div DWORD [ebp-4]
|
|
||||||
mov DWORD [ebp-12], eax
|
|
||||||
mov al, BYTE [ebp-12]
|
|
||||||
mov BYTE [ebp-5], al
|
|
||||||
mov eax, 0
|
|
||||||
mov al, BYTE [ebp-5]
|
|
||||||
imul eax, DWORD [ebp-4]
|
|
||||||
sub DWORD [ebp+8], eax
|
|
||||||
mov edx, DWORD [ebp-4]
|
|
||||||
mov eax, -858993459
|
|
||||||
mul edx
|
|
||||||
mov eax, edx
|
|
||||||
shr eax, 3
|
|
||||||
mov DWORD [ebp-4], eax
|
|
||||||
lea eax, [ebp-5]
|
|
||||||
add BYTE [eax], 48
|
|
||||||
sub esp, 12
|
|
||||||
mov eax, 0
|
|
||||||
mov al, BYTE [ebp-5]
|
|
||||||
push eax
|
|
||||||
call _putc
|
|
||||||
add esp, 16
|
|
||||||
jmp L5
|
|
||||||
L6:
|
|
||||||
sub esp, 12
|
|
||||||
mov al, BYTE [ebp+8]
|
|
||||||
add eax, 48
|
|
||||||
and eax, 255
|
|
||||||
push eax
|
|
||||||
call _putc
|
|
||||||
add esp, 16
|
|
||||||
leave
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_putDec:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
sub esp, 24
|
|
||||||
cmp DWORD [ebp+8], 0
|
|
||||||
jns L9
|
|
||||||
sub esp, 12
|
|
||||||
push 45
|
|
||||||
call _putc
|
|
||||||
add esp, 16
|
|
||||||
neg DWORD [ebp+8]
|
|
||||||
L9:
|
|
||||||
mov DWORD [ebp-4], 1
|
|
||||||
mov BYTE [ebp-5], 0
|
|
||||||
L10:
|
|
||||||
mov eax, DWORD [ebp+8]
|
|
||||||
cmp eax, DWORD [ebp-4]
|
|
||||||
jae L12
|
|
||||||
jmp L11
|
|
||||||
L12:
|
|
||||||
mov eax, DWORD [ebp-4]
|
|
||||||
mov edx, eax
|
|
||||||
sal edx, 2
|
|
||||||
add edx, eax
|
|
||||||
lea eax, [edx+edx]
|
|
||||||
mov DWORD [ebp-4], eax
|
|
||||||
jmp L10
|
|
||||||
L11:
|
|
||||||
mov edx, DWORD [ebp-4]
|
|
||||||
mov eax, -858993459
|
|
||||||
mul edx
|
|
||||||
mov eax, edx
|
|
||||||
shr eax, 3
|
|
||||||
mov DWORD [ebp-4], eax
|
|
||||||
L13:
|
|
||||||
cmp DWORD [ebp-4], 1
|
|
||||||
ja L15
|
|
||||||
jmp L14
|
|
||||||
L15:
|
|
||||||
mov edx, DWORD [ebp+8]
|
|
||||||
mov eax, edx
|
|
||||||
mov edx, 0
|
|
||||||
div DWORD [ebp-4]
|
|
||||||
mov DWORD [ebp-12], eax
|
|
||||||
mov al, BYTE [ebp-12]
|
|
||||||
mov BYTE [ebp-5], al
|
|
||||||
mov eax, 0
|
|
||||||
mov al, BYTE [ebp-5]
|
|
||||||
imul eax, DWORD [ebp-4]
|
|
||||||
sub DWORD [ebp+8], eax
|
|
||||||
mov edx, DWORD [ebp-4]
|
|
||||||
mov eax, -858993459
|
|
||||||
mul edx
|
|
||||||
mov eax, edx
|
|
||||||
shr eax, 3
|
|
||||||
mov DWORD [ebp-4], eax
|
|
||||||
lea eax, [ebp-5]
|
|
||||||
add BYTE [eax], 48
|
|
||||||
sub esp, 12
|
|
||||||
mov eax, 0
|
|
||||||
mov al, BYTE [ebp-5]
|
|
||||||
push eax
|
|
||||||
call _putc
|
|
||||||
add esp, 16
|
|
||||||
jmp L13
|
|
||||||
L14:
|
|
||||||
sub esp, 12
|
|
||||||
mov al, BYTE [ebp+8]
|
|
||||||
add eax, 48
|
|
||||||
and eax, 255
|
|
||||||
push eax
|
|
||||||
call _putc
|
|
||||||
add esp, 16
|
|
||||||
leave
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifndef __HIO_H__
|
|
||||||
#define __HIO_H__ __HIO_H__
|
|
||||||
|
|
||||||
void writeCursorPosition(dword pos);
|
|
||||||
dword getCursorPosition();
|
|
||||||
int putc(dword chr);
|
|
||||||
int printf(char *fmt, ...);
|
|
||||||
int puts(char *str);
|
|
||||||
int putDec(int number);
|
|
||||||
int putDecu(dword number);
|
|
||||||
int putHex(dword number);
|
|
||||||
void console_cls();
|
|
||||||
void console_scroll();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,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 @@
|
|||||||
|
ld -nodefaultlibs -nostdlib -T link.ld -o kernel.bin -Map .\lst\LDout.doc ks.o kernel.o asmfuncs.o
|
||||||
@@ -2,7 +2,7 @@ OUTPUT_FORMAT("binary")
|
|||||||
ENTRY(start)
|
ENTRY(start)
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
.text 0x100000 : {
|
.text 0xC0106000 : {
|
||||||
code = .; _code = .; __code = .;
|
code = .; _code = .; __code = .;
|
||||||
*(.text)
|
*(.text)
|
||||||
. = ALIGN(4096);
|
. = ALIGN(4096);
|
||||||
|
|||||||
@@ -1,245 +1,112 @@
|
|||||||
// mm.c
|
// mm.c
|
||||||
// 09/01/03 Josh Holtrop
|
// Author: Josh Holtrop
|
||||||
|
// Created: 09/01/03
|
||||||
|
// Modified: 12/28/03
|
||||||
|
|
||||||
// 0x368000 is first available byte (this is right after the kernel @ 1mb and the initrd @ 2mb, 1440kb.
|
//The total amount of physical memory available (bytes)
|
||||||
|
#define BITMAP_SIZE 0x20000
|
||||||
|
dword mm_totalmem = 0;
|
||||||
pageblock *first_pageblock = (pageblock *) 0;
|
dword mm_megabytes;
|
||||||
dword mm_totalmem = 0x100000; //start counting from 1mb
|
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()
|
void mm_init()
|
||||||
{
|
{
|
||||||
dword *memmap_entries = (dword *) 0x9040A;
|
dword memmap_entries = *(dword *)0xC009040A;
|
||||||
memmap_entry *maps = (memmap_entry *) 0x92000;
|
memmap_entry *maps = (memmap_entry *) 0xC0092000;
|
||||||
dword a;
|
dword a;
|
||||||
for (a=0;a<(*memmap_entries);a++)
|
for (a = 0; a < BITMAP_SIZE; a++)
|
||||||
|
{
|
||||||
|
page_bitmap[a] = 0xFF; //all pages used
|
||||||
|
}
|
||||||
|
for (a = 0; a < memmap_entries; a++)
|
||||||
{
|
{
|
||||||
if (maps[a].attributes == 1) // (1) mem free to OS
|
if (maps[a].attributes == 1) // (1) mem free to OS
|
||||||
{
|
{
|
||||||
mm_totalmem += maps[a].limit.lowdword;
|
mm_totalmem += maps[a].limit.lowdword;
|
||||||
if ((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)
|
if (maps[a].base.lowdword < FREERAM_START)
|
||||||
{
|
{
|
||||||
maps[a].limit.lowdword = maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword);
|
mm_pfreen(FREERAM_START, (maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword)) >> 12);
|
||||||
maps[a].base.lowdword = FREERAM_START; //block at least 4kb, starts >= FREERAM_START
|
|
||||||
}
|
}
|
||||||
if (first_pageblock == 0) //no pageblock page set up yet, so set it up here
|
else
|
||||||
{
|
{
|
||||||
first_pageblock = (pageblock *) maps[a].base.lowdword;
|
mm_pfreen(maps[a].base.lowdword, maps[a].limit.lowdword >> 12); //set the appropriate bits as "free" in the page bitmap
|
||||||
maps[a].base.lowdword += 4096;
|
|
||||||
maps[a].limit.lowdword -= 4096;
|
|
||||||
mm_init_pageblockpage(first_pageblock);
|
|
||||||
first_pageblock->base = maps[a].base.lowdword;
|
|
||||||
first_pageblock->length = maps[a].limit.lowdword / 4096;
|
|
||||||
first_pageblock->pid = MM_PB_AVAIL;
|
|
||||||
}
|
}
|
||||||
else //first_pageblock already set up, add on segment
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mm_totalmem % 0x100000)
|
||||||
|
mm_megabytes = (mm_totalmem >> 20) + 1;
|
||||||
|
else
|
||||||
|
mm_megabytes = mm_totalmem >> 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function frees a certain number of pages starting at the address
|
||||||
|
// specified in base for a length of pages pages
|
||||||
|
void mm_pfreen(dword base, dword pages)
|
||||||
|
{
|
||||||
|
dword a;
|
||||||
|
dword max = base + (pages << 12);
|
||||||
|
for (a = base; a < max; a += 4096)
|
||||||
|
{
|
||||||
|
mm_pfree(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function frees a single page
|
||||||
|
void mm_pfree(dword base)
|
||||||
|
{
|
||||||
|
// dword pageNumber = base >> 12; // >>12 == /4096
|
||||||
|
dword byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8
|
||||||
|
dword bitNumber = (base >> 12) % 8; //pageNumber % 8;
|
||||||
|
page_bitmap[byteNumber] = page_bitmap[byteNumber] & ((0x01 << bitNumber) ^ 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function allocates a single page, returning its physical address
|
||||||
|
void *mm_palloc()
|
||||||
|
{
|
||||||
|
dword bite;
|
||||||
|
for (bite = 0; bite < BITMAP_SIZE; bite++)
|
||||||
|
{
|
||||||
|
if (page_bitmap[bite] != 0xFF) //there is an available page within this 8-page region
|
||||||
|
{
|
||||||
|
int bit;
|
||||||
|
for (bit = 0; bit < 8; bit++)
|
||||||
|
{
|
||||||
|
if (!(page_bitmap[bite] & (1 << bit))) //this bite/bit combination is available
|
||||||
{
|
{
|
||||||
pageblock *pb = first_pageblock;
|
page_bitmap[bite] = page_bitmap[bite] | (1 << bit); //set page as used
|
||||||
for (;;)
|
return (void *)((bite << 15) | (bit << 12));
|
||||||
{
|
|
||||||
if (pb->pid == MM_PB_NP)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
pb++;
|
|
||||||
}
|
|
||||||
pb->base = maps[a].base.lowdword;
|
|
||||||
pb->length = maps[a].limit.lowdword / 4096;
|
|
||||||
pb->pid = MM_PB_AVAIL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (first_pageblock == 0)
|
return 0; //no free page
|
||||||
{
|
|
||||||
printf("ERROR! NO INITIAL PAGE BLOCK CREATED.");
|
|
||||||
asm("cli");
|
|
||||||
asm("hlt");
|
|
||||||
for (;;)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function reports the number of bytes of free physical memory
|
||||||
|
dword mm_freemem()
|
||||||
void mm_init_pageblockpage(pageblock *pbp)
|
|
||||||
{
|
{
|
||||||
int a;
|
dword a;
|
||||||
for (a=0; a<256; a++) // 256 pageblock entries * 16 bytes per page block entry = 4096 bytes (1 page of pageblock entries)
|
dword pages = 0;
|
||||||
|
for (a = 0; a < BITMAP_SIZE; a++)
|
||||||
{
|
{
|
||||||
pbp[a].base = 0;
|
int bit;
|
||||||
pbp[a].length = 0;
|
for (bit = 0; bit < 8; bit++)
|
||||||
pbp[a].pid = MM_PB_NP;
|
|
||||||
if (a<255)
|
|
||||||
pbp[a].link = (dword)(&pbp[a+1]);
|
|
||||||
else
|
|
||||||
pbp[a].link = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *mm_palloc(dword numpages, dword proc_pid)
|
|
||||||
{
|
|
||||||
if (proc_pid < KERNEL_PID)
|
|
||||||
return 0;
|
|
||||||
pageblock *pb = first_pageblock;
|
|
||||||
if (mm_freeentries() < 2)
|
|
||||||
{
|
|
||||||
if(mm_new_pageblock_page() == 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pageblock *newentry = mm_nextpageblockentry();
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if ((pb->pid == MM_PB_AVAIL) && (pb->length >= numpages))
|
|
||||||
break;
|
|
||||||
if (pb->link == 0)
|
|
||||||
return 0;
|
|
||||||
pb = (pageblock *)pb->link;
|
|
||||||
}
|
|
||||||
if (pb->length == numpages) //dont need a new entry, just mark this one as used :)
|
|
||||||
{
|
|
||||||
pb->pid = proc_pid;
|
|
||||||
return (void *)pb->base;
|
|
||||||
}
|
|
||||||
else //subtract out allocated number of pages from length
|
|
||||||
{
|
|
||||||
newentry->base = pb->base;
|
|
||||||
newentry->length = numpages;
|
|
||||||
newentry->pid = proc_pid;
|
|
||||||
pb->base += (numpages * 4096);
|
|
||||||
pb->length -= numpages;
|
|
||||||
return (void *)newentry->base;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
dword mm_freeentries()
|
|
||||||
{
|
|
||||||
pageblock *pb = first_pageblock;
|
|
||||||
dword counter = 0;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (pb->pid == MM_PB_NP)
|
|
||||||
counter++;
|
|
||||||
if (pb->link == 0)
|
|
||||||
return counter;
|
|
||||||
pb = (pageblock *) pb->link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pageblock *mm_new_pageblock_page() //as of 09/26/03 this method leaks 4kb main memory per call, unrecoverable
|
|
||||||
{
|
|
||||||
pageblock *pb = first_pageblock;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if ((pb->pid == MM_PB_AVAIL) && (pb->length > 1))
|
|
||||||
{
|
{
|
||||||
pageblock *retval = (pageblock *)pb->base;
|
if (!(page_bitmap[a] & (1 << bit)))
|
||||||
pb->base += 4096;
|
pages++;
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (ptr == 0)
|
|
||||||
return 2;
|
|
||||||
pageblock *pb = first_pageblock;
|
|
||||||
dword tofree = (dword) ptr;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (pb->base == tofree) // && (pb->pid == MM_PB_USED))
|
|
||||||
{
|
|
||||||
pb->pid = MM_PB_AVAIL; //found block, mark available / coalesce it
|
|
||||||
mm_coalesce(pb);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (pb->link == 0)
|
|
||||||
return 1;
|
|
||||||
pb = (pageblock *) pb->link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pageblock *mm_lastpageblockentry()
|
|
||||||
{
|
|
||||||
pageblock *pb = first_pageblock;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (pb->link == 0)
|
|
||||||
return pb;
|
|
||||||
pb = (pageblock *)pb->link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pageblock *mm_nextpageblockentry()
|
|
||||||
{
|
|
||||||
pageblock *pb = first_pageblock;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (pb->pid == MM_PB_NP)
|
|
||||||
return pb;
|
|
||||||
if (pb->link == 0)
|
|
||||||
return 0;
|
|
||||||
pb = (pageblock *)pb->link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
dword mm_freemem()
|
|
||||||
{
|
|
||||||
dword amount = 0;
|
|
||||||
pageblock *pb = first_pageblock;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (pb->pid == MM_PB_AVAIL)
|
|
||||||
amount += (pb->length)*4096;
|
|
||||||
if (pb->link == 0)
|
|
||||||
return amount;
|
|
||||||
pb = (pageblock *) pb->link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mm_coalesce(pageblock *pb)
|
|
||||||
{
|
|
||||||
pageblock *pbc = first_pageblock;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (pbc->pid == pb->pid) //pid fields must match, both same process, both avail, or both not present
|
|
||||||
{
|
|
||||||
if ((pbc->base + (pbc->length * 4096)) == pb->base) //pbc ends where pb starts
|
|
||||||
{
|
|
||||||
pbc->length += pb->length;
|
|
||||||
pb->pid = MM_PB_NP;
|
|
||||||
mm_coalesce(pbc); //recursion: checks for any more page blocks to coalesce if one found
|
|
||||||
return; //exit this recursion...
|
|
||||||
}
|
|
||||||
if ((pb->base + (pb->length * 4096)) == pbc->base) //pb ends where pbc starts
|
|
||||||
{
|
|
||||||
pb->length += pbc->length;
|
|
||||||
pbc->pid = MM_PB_NP;
|
|
||||||
mm_coalesce(pb);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pbc->link == 0)
|
|
||||||
return;
|
|
||||||
pbc = (pageblock *)pbc->link;
|
|
||||||
}
|
}
|
||||||
|
return pages << 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,28 +7,14 @@ typedef struct {
|
|||||||
} __attribute__((packed)) memmap_entry;
|
} __attribute__((packed)) memmap_entry;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
dword base;
|
|
||||||
dword length; //in pages
|
|
||||||
dword pid; //normally PID of process, use NP, AVAIL for special flags
|
|
||||||
dword link; //leave dword instead of pointer so i dont have to worry about pointer arithmetic
|
|
||||||
} __attribute__ ((packed)) pageblock; //16 byte pageblock entry - 256 entries = 1 page
|
|
||||||
|
|
||||||
|
|
||||||
void mm_init();
|
void mm_init();
|
||||||
void mm_init_pageblockpage(pageblock *pbp);
|
void mm_pfreen(dword base, dword pages);
|
||||||
void *mm_palloc(dword numpages, dword proc_pid);
|
void mm_pfree(dword base);
|
||||||
void mm_coalesce(pageblock *pb);
|
void *mm_palloc();
|
||||||
int mm_pfree(void *ptr);
|
|
||||||
dword mm_freeentries();
|
|
||||||
dword mm_freemem();
|
dword mm_freemem();
|
||||||
pageblock *mm_new_pageblock_page();
|
|
||||||
pageblock *mm_lastpageblockentry();
|
|
||||||
pageblock *mm_nextpageblockentry();
|
|
||||||
|
|
||||||
|
|
||||||
#define MM_PB_NP 0x00 //00000000
|
|
||||||
#define MM_PB_AVAIL 0x01 //00000001
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// Author: Josh Holtrop
|
// Author: Josh Holtrop
|
||||||
|
|
||||||
|
|
||||||
|
//This method initializes the ps/2 mouse
|
||||||
void mouse_init()
|
void mouse_init()
|
||||||
{
|
{
|
||||||
outportb(0x64, 0x20); //tell keyboard controller we are going to read keyboard controller command byte
|
outportb(0x64, 0x20); //tell keyboard controller we are going to read keyboard controller command byte
|
||||||
@@ -15,17 +16,18 @@ void mouse_init()
|
|||||||
outportb(0x64, 0xD4); //send command to mouse, not kbd
|
outportb(0x64, 0xD4); //send command to mouse, not kbd
|
||||||
outportb(0x60, 0xF4); //enable data reporting
|
outportb(0x60, 0xF4); //enable data reporting
|
||||||
|
|
||||||
|
mouse_x = video_mode.XResolution >> 1;
|
||||||
|
mouse_y = video_mode.YResolution >> 1;
|
||||||
|
|
||||||
//outportb(0x64, 0xD4);
|
//outportb(0x64, 0xD4);
|
||||||
//outportb(0x60, 0xE7); //scaling 2:1
|
//outportb(0x60, 0xE7); //scaling 2:1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//This method is called when a mouse interrupt occurs
|
||||||
void isr_mouse()
|
void isr_mouse()
|
||||||
{
|
{
|
||||||
byte inb = inportb(0x60); //read mouse byte
|
byte inb = inportb(0x60); //read mouse byte
|
||||||
//printf("InB: %x\n", inb);
|
|
||||||
//return;
|
|
||||||
if ((inb == 0xFA) && (mouse_bytesRead < 1)) //ACK
|
if ((inb == 0xFA) && (mouse_bytesRead < 1)) //ACK
|
||||||
return;
|
return;
|
||||||
mouse_inbuffer[mouse_bytesRead] = inb;
|
mouse_inbuffer[mouse_bytesRead] = inb;
|
||||||
@@ -37,16 +39,18 @@ void isr_mouse()
|
|||||||
int adjy = (char) mouse_inbuffer[2];
|
int adjy = (char) mouse_inbuffer[2];
|
||||||
mouse_x += adjx;
|
mouse_x += adjx;
|
||||||
mouse_y -= adjy; //-= because screen y coordinates are opposite mouse y coordinates
|
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
|
if (mouse_inbuffer[0] & 0x01) //left button
|
||||||
{
|
video_pset(mouse_x, mouse_y, 0x00FF8800);
|
||||||
video_pset(VXR/2+mouse_x, VYR/2+mouse_y, 0x00FFFFFF);
|
|
||||||
printf("X: %d, Y: %d\n", mouse_x, mouse_y);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
video_pset(mouse_x, mouse_y, 0x00FFFFFF);
|
||||||
video_pset(VXR/2+mouse_x, VYR/2+mouse_y, 0x00000000);
|
|
||||||
printf("X: %d, Y: %d\n", mouse_x, mouse_y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
// Author: Josh Holtrop
|
// Author: Josh Holtrop
|
||||||
|
|
||||||
|
|
||||||
int mouse_x = 0;
|
int mouse_x;
|
||||||
int mouse_y = 0;
|
int mouse_y;
|
||||||
int mouse_bytesRead = 0;
|
int mouse_bytesRead = 0;
|
||||||
byte mouse_inbuffer[16];
|
byte mouse_inbuffer[16];
|
||||||
|
|
||||||
|
|||||||
@@ -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 0 ; 0025h - Reserved (FAT32)
|
||||||
DB 29H ; 0026h - Extended boot record sig (FAT32)
|
DB 29H ; 0026h - Extended boot record sig (FAT32)
|
||||||
brSerialNum DD 404418EAH ; 0027h - Volume serial number
|
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
|
brFSID DB 'FAT12 ' ; 0036h - File System ID
|
||||||
;------------------------------------------------------------------------
|
;------------------------------------------------------------------------
|
||||||
|
|
||||||
start:
|
start:
|
||||||
jmp 0:jmphere ;ensure that cs=0 and ip=0x7c...
|
jmp 0:jmphere ;ensure that cs=0 and ip=0x7c00...
|
||||||
jmphere:
|
jmphere:
|
||||||
;dl=drive number, save it!
|
;dl=drive number, save it!
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
@@ -88,7 +88,7 @@ unreal:
|
|||||||
pop es ;segments back, with 4gb limits!
|
pop es ;segments back, with 4gb limits!
|
||||||
sti
|
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 ax, 0x0209 ;FAT1
|
||||||
mov cx, 0x0002
|
mov cx, 0x0002
|
||||||
xor dh, dh
|
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
|
jmp found_file ;good file, ds:si points to start of root directory entry
|
||||||
goon:
|
goon:
|
||||||
pop si
|
pop si
|
||||||
|
add si, 32
|
||||||
pop cx
|
pop cx
|
||||||
loop loop_compare
|
loop loop_compare
|
||||||
|
|
||||||
@@ -147,29 +148,43 @@ got_rd:
|
|||||||
mov [ds:BOOT_HASRD], al
|
mov [ds:BOOT_HASRD], al
|
||||||
pop ds ;ds=0
|
pop ds ;ds=0
|
||||||
cmp al, 0 ;dont load rd
|
cmp al, 0 ;dont load rd
|
||||||
jz no_rd
|
jnz yes_rd
|
||||||
|
jmp no_rd
|
||||||
|
yes_rd:
|
||||||
mov cx, 80
|
mov cx, 80
|
||||||
mov edi, 0xb8000+160*4
|
mov edi, 0xb8000+160*4
|
||||||
filler_loop:
|
filler_loop: ;draw a red bar
|
||||||
mov word [ds:edi], 0x0400+177
|
mov word [ds:edi], 0x0400+177
|
||||||
inc edi
|
inc edi
|
||||||
inc edi
|
inc edi
|
||||||
loop filler_loop
|
loop filler_loop
|
||||||
|
|
||||||
mov cx, 80 ;80 cylinders to read
|
mov cx, 80 ;80 cylinders to read
|
||||||
xor si, si
|
xor si, si ;start at cylinder 0
|
||||||
mov edi, BOOT_RD_ADD ;ram disk address
|
mov edi, BOOT_RD_ADD ;ram disk address
|
||||||
read_cylinder:
|
read_cylinder:
|
||||||
push cx
|
push cx
|
||||||
mov bx, 0x0100
|
|
||||||
|
mov bx, 0x0100 ;read sectors from head 0
|
||||||
mov es, bx
|
mov es, bx
|
||||||
xor bx, bx
|
xor bx, bx ;es:bx = data buffer for read
|
||||||
mov ax, 0x0224
|
mov ax, 0x0212 ;ah = int 0x13 function 2, al = number of sectors to read
|
||||||
mov cx, si
|
mov cx, si ;what cyl. we are on is now in cx
|
||||||
mov ch, cl
|
mov ch, cl ;ch = cyl. number
|
||||||
mov cl, 1
|
mov cl, 1 ;cl = sector number 1-63
|
||||||
xor dx, dx
|
xor dx, dx ;dh = head number
|
||||||
mov dl, [gs:BOOT_DRIVE]
|
mov dl, [gs:BOOT_DRIVE] ;dl = drive number
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
mov bx, 0x0100 ;now read sectors from head 1
|
||||||
|
mov es, bx
|
||||||
|
mov bx, 9216 ;es:bx = data buffer for read
|
||||||
|
mov ax, 0x0212 ;ah = int 0x13 function 2, al = number of sectors to read
|
||||||
|
mov cx, si ;what cyl. we are on is now in cx
|
||||||
|
mov ch, cl ;ch = cyl. number
|
||||||
|
mov cl, 1 ;cl = sector number 1-63
|
||||||
|
mov dh, 1 ;dh = head number
|
||||||
|
mov dl, [gs:BOOT_DRIVE] ;dl = drive number
|
||||||
int 0x13
|
int 0x13
|
||||||
|
|
||||||
mov ebx, 0xb8000
|
mov ebx, 0xb8000
|
||||||
@@ -836,7 +851,7 @@ puthex2_goon2:
|
|||||||
ret
|
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_rd1: db "1. Do not load an initial ram disk", 0
|
||||||
txt_rd2: db "2. Load initial ram disk from floppy", 0
|
txt_rd2: db "2. Load initial ram disk from floppy", 0
|
||||||
txt_input: db "Enter your selection: ", 0
|
txt_input: db "Enter your selection: ", 0
|
||||||
@@ -889,11 +904,43 @@ KERNEL_DATA equ $-gdt
|
|||||||
db 0x00
|
db 0x00
|
||||||
db 0x00
|
db 0x00
|
||||||
db 0x92
|
db 0x92
|
||||||
db 0xcf ;cf
|
db 0xcf
|
||||||
db 0x00
|
db 0x00
|
||||||
|
|
||||||
gdt_end:
|
gdt_end:
|
||||||
|
|
||||||
|
|
||||||
|
;-------------------------------------------------------
|
||||||
|
gdtr32:
|
||||||
|
dw gdt_end32-gdt32-1
|
||||||
|
dd gdt32
|
||||||
|
gdt32:
|
||||||
|
dd 0
|
||||||
|
dd 0
|
||||||
|
|
||||||
|
;a base of 0x4000_0000, when added to 0xC000_0000 will produce 0x0000_0000 physical before paging in effect
|
||||||
|
KERNEL_CODE32 equ $-gdt32
|
||||||
|
db 0xff ;limit 7:0
|
||||||
|
db 0xff ;limit 15:8
|
||||||
|
db 0x00 ;base 7:0
|
||||||
|
db 0x00 ;base 15:8
|
||||||
|
db 0x00 ;base 23:16
|
||||||
|
db 0x9a ;access
|
||||||
|
db 0xcf ;flags / limit 19:16
|
||||||
|
db 0x40 ;base 31:24
|
||||||
|
|
||||||
|
KERNEL_DATA32 equ $-gdt32
|
||||||
|
db 0xff ;segment 16 = 4gb data
|
||||||
|
db 0xff
|
||||||
|
db 0x00
|
||||||
|
db 0x00
|
||||||
|
db 0x00
|
||||||
|
db 0x92
|
||||||
|
db 0xcf
|
||||||
|
db 0x40
|
||||||
|
|
||||||
|
gdt_end32:
|
||||||
|
|
||||||
;------------------------------------------------------
|
;------------------------------------------------------
|
||||||
go_pm:
|
go_pm:
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
@@ -908,12 +955,16 @@ go_pm:
|
|||||||
|
|
||||||
bits 32
|
bits 32
|
||||||
pmode:
|
pmode:
|
||||||
mov ax, KERNEL_DATA
|
lgdt [gdtr32]
|
||||||
|
jmp KERNEL_CODE32:pmode_offsetted+0xC0000000
|
||||||
|
|
||||||
|
pmode_offsetted:
|
||||||
|
mov ax, KERNEL_DATA32
|
||||||
mov es, ax
|
mov es, ax
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
mov fs, ax
|
mov fs, ax
|
||||||
mov gs, ax
|
mov gs, ax
|
||||||
jmp KERNEL_CODE:BOOT_KERNEL_ADD
|
jmp KERNEL_CODE:BOOT_KERNEL_ADD+0xC0000000
|
||||||
|
|
||||||
kernel: db "KERNEL BIN", 0
|
kernel: db "KERNEL BIN", 0
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,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 };
|
||||||
|
|
||||||
@@ -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,147 +1,176 @@
|
|||||||
//video.c
|
//video.c
|
||||||
// 08/13/03 Josh Holtrop
|
// 08/13/03 Josh Holtrop
|
||||||
|
// Modified: 11/12/03
|
||||||
|
|
||||||
|
|
||||||
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)
|
switch(video_mode.BitsPerPixel)
|
||||||
{
|
{
|
||||||
case 16:
|
case 16:
|
||||||
vid_ptr16 = (word *) video_mode.PhysBasePtr;
|
video_psetp = &video_psetp16;
|
||||||
break;
|
break;
|
||||||
case 24:
|
case 24:
|
||||||
vid_ptr24 = (byte *) video_mode.PhysBasePtr;
|
video_psetp = &video_psetp24;
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
vid_ptr32 = (dword *) video_mode.PhysBasePtr;
|
video_psetp = &video_psetp32;
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
if (x1 > x2)
|
||||||
{
|
{
|
||||||
int tmp = x2;
|
int tmp = x2;
|
||||||
x2 = x1;
|
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 pixel = y*video_mode.XResolution+x1;
|
||||||
int a;
|
for (; x1 <= x2; x1++)
|
||||||
for (a = 0; a <= (x2-x1); a++)
|
|
||||||
{
|
{
|
||||||
video_psetp(pixel, color);
|
video_psetp(pixel++, color);
|
||||||
pixel++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
if (y1 > y2)
|
||||||
{
|
{
|
||||||
int tmp = y2;
|
int tmp = y2;
|
||||||
y2 = y1;
|
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 pixel = y1*video_mode.XResolution+x;
|
||||||
int a;
|
for (; y1 <= y2; y1++)
|
||||||
for (a = 0; a <= (y2-y1); a++)
|
|
||||||
{
|
{
|
||||||
video_psetp(pixel, color);
|
video_psetp(pixel, color);
|
||||||
pixel+=video_mode.XResolution;
|
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(y1, x1, x2, color);
|
||||||
video_horiz(y2, x1, x2, color);
|
video_horiz(y2, x1, x2, color);
|
||||||
video_vert(x1, y1, y2, color);
|
video_vert(x1, y1, y2, color);
|
||||||
video_vert(x2, 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)
|
if (y2 < y1)
|
||||||
{
|
{
|
||||||
int tmp = y2;
|
int tmp = y2;
|
||||||
y2 = y1;
|
y2 = y1;
|
||||||
y1 = tmp;
|
y1 = tmp;
|
||||||
}
|
}
|
||||||
int a;
|
for (; y1 <= y2; y1++)
|
||||||
for (a = 0; a <= (y2-y1); a++)
|
video_horiz(y1, x1, x2, color);
|
||||||
video_horiz(y1+a, x1, x2, color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Draws a single pixel
|
||||||
inline void video_pset(int x, int y, dword color)
|
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);
|
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:
|
for (y = 0; y < 25; y++)
|
||||||
vid_ptr16[pixel] = ((color&0xFF)>>3) | ((((color>>8)&0xFF)>>2)<<5) | ((((color>>16)&0xFF)>>3)<<11);
|
{
|
||||||
//vid_ptr16[pixel] = ((color&0xFF)>>3) | ((((color>>8)&0xFF)>>3)<<5) | ((((color>>16)&0xFF)>>3)<<10);
|
video_renderChar(x*6+10, y*10+10, console_memory[y*80+x], 0x00FFFFFF);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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,19 +1,22 @@
|
|||||||
//video.h
|
//video.h
|
||||||
// 08/18/03 Josh Holtrop
|
// 08/18/03 Josh Holtrop
|
||||||
|
// Modified: 12/28/03
|
||||||
|
|
||||||
|
void video_init();
|
||||||
void video_init();
|
void video_horiz(int y, int x1, int x2, dword color);
|
||||||
void video_horiz(int y, int x1, int x2, dword color);
|
void video_vert(int x, int y1, int y2, 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_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_rectf(int x1, int y1, int x2, int y2, dword color);
|
|
||||||
inline void video_pset(int x, int y, 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{
|
typedef struct{
|
||||||
word ModeAttributes;
|
word ModeAttributes;
|
||||||
byte WinAAttributes;
|
byte WinAAttributes;
|
||||||
@@ -53,11 +56,14 @@ typedef struct{
|
|||||||
byte Reserved[206];
|
byte Reserved[206];
|
||||||
} ModeInfoBlock;
|
} ModeInfoBlock;
|
||||||
|
|
||||||
|
|
||||||
ModeInfoBlock video_mode;
|
ModeInfoBlock video_mode;
|
||||||
byte *vid_ptr24;
|
dword videoMode = 0; //what video mode # we are in, 0 for console mode
|
||||||
word *vid_ptr16;
|
word *vid_ptr16 = (word *)0xF0000000;
|
||||||
dword *vid_ptr32;
|
byte *vid_ptr24 = (byte *)0xF0000000;
|
||||||
|
dword *vid_ptr32 = (dword *)0xF0000000;
|
||||||
|
word console_memory[2000]; //holds a copy of the console's memory
|
||||||
|
void (*video_psetp)(int, dword) = video_psetpnull; //function pointer to set a pixel
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,349 @@
|
|||||||
|
|
||||||
// vmm.c
|
// vmm.c
|
||||||
// Author: Josh Holtrop
|
// Author: Josh Holtrop
|
||||||
// Date: 09/30/03
|
// Date: 09/30/03
|
||||||
|
// Rewritten from scratch: 12/23/03
|
||||||
|
// 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)
|
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
|
||||||
int free(void *ptr);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -25,3 +351,4 @@ int free(void *ptr);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,11 +1,53 @@
|
|||||||
|
|
||||||
// vmm.h
|
// vmm.h
|
||||||
// Author: Josh Holtrop
|
// Author: Josh Holtrop
|
||||||
// Date: 09/30/03
|
// Date: 09/30/03
|
||||||
|
// Rewritten from scratch: 12/23/03
|
||||||
|
// Modified: 12/30/03
|
||||||
|
|
||||||
|
|
||||||
|
#define VMM_HE_UNUSED 0 //available entry
|
||||||
|
#define VMM_HE_FREE 1 //free section of memory
|
||||||
|
#define VMM_HE_USED 2 //used section of memory
|
||||||
|
#define VMM_HE_HOLE 3 //a "hole" (unmapped) section of virtual memory
|
||||||
|
#define VMM_HE_HEB 4 //HeapEntryBlock
|
||||||
|
|
||||||
|
#define VMM_MALLOC_GRANULARITY 4 //granularity for all memory requests
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
dword base; //virtual base address
|
||||||
|
dword size; //size in bytes
|
||||||
|
dword attributes; //free/used/hole
|
||||||
|
dword link; //link to next HeapEntry
|
||||||
|
} __attribute__((packed)) HeapEntry;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
HeapEntry entry[256]; //256 HeapEntry objects = 4kb (1 page)
|
||||||
|
} __attribute__((packed)) HeapEntryBlock;
|
||||||
|
|
||||||
|
|
||||||
|
void vmm_init();
|
||||||
void *malloc(dword bytes);
|
void *malloc(dword bytes);
|
||||||
int free(void *ptr);
|
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