Compare commits
4 Commits
9cbecc1689
...
6e633b44b7
| Author | SHA1 | Date | |
|---|---|---|---|
| 6e633b44b7 | |||
|
b8a155fada
|
|||
|
091f94f89e
|
|||
|
b469952d91
|
2
Makefile
2
Makefile
@@ -2,7 +2,7 @@ SOURCES = src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
rm -f *.o
|
rm -f *.o
|
||||||
x86_64-elf-gcc -g -c -Isrc $(SOURCES) -Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel
|
x86_64-elf-gcc -g -c -Isrc $(SOURCES) -Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-omit-frame-pointer -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel
|
||||||
objcopy -O elf64-x86-64 -B i386 -I binary zap-light16.psf zap-light16.o
|
objcopy -O elf64-x86-64 -B i386 -I binary zap-light16.psf zap-light16.o
|
||||||
nasm -f elf64 src/idt/idt.S -o idt_stub.o
|
nasm -f elf64 src/idt/idt.S -o idt_stub.o
|
||||||
x86_64-elf-ld -o pepperk -T linker.ld *.o
|
x86_64-elf-ld -o pepperk -T linker.ld *.o
|
||||||
|
|||||||
@@ -185,13 +185,14 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 32:
|
case 32:
|
||||||
//DEBUG("Tick!");
|
//DEBUG("Timer Interrupt");
|
||||||
ticks++;
|
ticks++;
|
||||||
// Send an EOI so that we can continue having interrupts
|
// Send an EOI so that we can continue having interrupts
|
||||||
outb(0x20, 0x20);
|
outb(0x20, 0x20);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 33:
|
case 33:
|
||||||
|
DEBUG("Keyboard Interrupt");
|
||||||
keyboard_handler();
|
keyboard_handler();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -201,12 +201,11 @@ void keyboard_handler()
|
|||||||
|
|
||||||
if (c)
|
if (c)
|
||||||
{
|
{
|
||||||
|
// Should probably have a keyboard buffer here... instead of this
|
||||||
putchar(c);
|
putchar(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
skputs("key pressed!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of Interrupt (to master PIC)
|
// End of Interrupt (to master PIC)
|
||||||
@@ -233,5 +232,11 @@ void keyboard_init(unsigned char layout)
|
|||||||
skputs("Unsupported layout.");
|
skputs("Unsupported layout.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unmask IRQ1
|
||||||
|
uint8_t mask = inb(0x21);
|
||||||
|
mask &= ~(1 << 1);
|
||||||
|
outb(0x21, mask);
|
||||||
|
|
||||||
DEBUG("PS/2 Keyboard initialized");
|
DEBUG("PS/2 Keyboard initialized");
|
||||||
}
|
}
|
||||||
@@ -23,71 +23,25 @@ uint8_t* glyphs = _binary_zap_light16_psf_start + sizeof(PSF1_Header);
|
|||||||
#define FONT_WIDTH 8
|
#define FONT_WIDTH 8
|
||||||
#define FONT_HEIGHT font->characterSize
|
#define FONT_HEIGHT font->characterSize
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Character cursor
|
// Character cursor
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
unsigned int x;
|
size_t x;
|
||||||
unsigned int y;
|
size_t y;
|
||||||
} Cursor;
|
} Cursor;
|
||||||
|
|
||||||
Cursor cursor = {0};
|
static Cursor cursor = {0, 0};
|
||||||
|
|
||||||
unsigned char* fb;
|
static uint8_t* fb;
|
||||||
|
static struct limine_framebuffer* framebuffer;
|
||||||
struct limine_framebuffer* framebuffer;
|
|
||||||
|
|
||||||
uint8_t lines_length[MAX_LINES];
|
uint8_t lines_length[MAX_LINES];
|
||||||
|
|
||||||
int term_init()
|
static inline size_t term_max_cols(void)
|
||||||
{
|
{
|
||||||
// Get framebuffer address from Limine struct
|
return framebuffer->width / FONT_WIDTH;
|
||||||
|
|
||||||
if (boot_ctx.fb)
|
|
||||||
{
|
|
||||||
fb = boot_ctx.fb->address;
|
|
||||||
framebuffer = boot_ctx.fb;
|
|
||||||
DEBUG("terminal initialized, fb=0x%p (width=%u height=%u pitch=%u bpp=%u)", fb, framebuffer->width, framebuffer->height, framebuffer->pitch, framebuffer->bpp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are marked "static" because we don't wanna expose them all around
|
|
||||||
// AKA they should just be seen here (kind of like private functions in cpp)
|
|
||||||
static void putpixel(int x, int y, int color)
|
|
||||||
{
|
|
||||||
// Depth isn't part of limine_framebuffer attributes so it will be 4
|
|
||||||
unsigned pos = x*4 + y*framebuffer->pitch;
|
|
||||||
fb[pos] = color & 255; // blue channel
|
|
||||||
fb[pos+1] = (color >> 8) & 255; // green
|
|
||||||
fb[pos+2] = (color >> 16) & 255; // blue
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw_char(char c, int px, int py, int fg, int bg)
|
|
||||||
{
|
|
||||||
uint8_t* glyph = glyphs + ((unsigned char)c * FONT_HEIGHT);
|
|
||||||
|
|
||||||
for (size_t y=0; y<FONT_HEIGHT; y++)
|
|
||||||
{
|
|
||||||
uint8_t row = glyph[y];
|
|
||||||
for (size_t x=0; x<8; x++)
|
|
||||||
{
|
|
||||||
int color = (row & (0x80 >> x)) ? fg : bg;
|
|
||||||
putpixel(px+x, py+y, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void erase_char(int px, int py)
|
|
||||||
{
|
|
||||||
for (size_t y=0; y<FONT_HEIGHT; y++)
|
|
||||||
{
|
|
||||||
for (size_t x=0; x<8; x++)
|
|
||||||
{
|
|
||||||
// Black
|
|
||||||
putpixel(px+x, py+y, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t term_max_lines(void)
|
static inline size_t term_max_lines(void)
|
||||||
@@ -95,23 +49,80 @@ static inline size_t term_max_lines(void)
|
|||||||
return framebuffer->height / FONT_HEIGHT;
|
return framebuffer->height / FONT_HEIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void term_scroll()
|
int term_init()
|
||||||
{
|
{
|
||||||
const size_t row_height = FONT_HEIGHT;
|
// Get framebuffer address from Limine struct
|
||||||
const size_t row_bytes = framebuffer->pitch;
|
|
||||||
const size_t screen_rows = framebuffer->height;
|
|
||||||
|
|
||||||
// Move framebuffer up by one text row
|
if (!boot_ctx.fb)
|
||||||
//memmove(fb, fb + row_height * row_bytes, (screen_rows - row_height) * row_bytes);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < (screen_rows - row_height) * row_bytes; i++)
|
|
||||||
{
|
{
|
||||||
fb[i] = fb[i + row_height * row_bytes];
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear last text row
|
framebuffer = boot_ctx.fb;
|
||||||
size_t clear_start = (screen_rows - row_height) * row_bytes;
|
fb = (uint8_t*)framebuffer->address;
|
||||||
memset(fb + clear_start, 0, row_height * row_bytes);
|
|
||||||
|
memset(lines_length, 0, sizeof(lines_length));
|
||||||
|
|
||||||
|
DEBUG("terminal initialized, fb=0x%p (width=%u height=%u pitch=%u bpp=%u)", fb, framebuffer->width, framebuffer->height, framebuffer->pitch, framebuffer->bpp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are marked "static" because we don't wanna expose them all around
|
||||||
|
// AKA they should just be seen here (kind of like private functions in cpp)
|
||||||
|
static inline void putpixel(size_t x, size_t y, uint32_t color)
|
||||||
|
{
|
||||||
|
// Guard so we don't write past fb boundaries
|
||||||
|
if (x >= framebuffer->width || y >= framebuffer->height) return;
|
||||||
|
// Depth isn't part of limine_framebuffer attributes so it will be 4
|
||||||
|
size_t pos = x*4 + y*framebuffer->pitch;
|
||||||
|
fb[pos] = color & 255; // blue channel
|
||||||
|
fb[pos+1] = (color >> 8) & 255; // green
|
||||||
|
fb[pos+2] = (color >> 16) & 255; // blue
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_char(char c, size_t px, size_t py, uint32_t fg, uint32_t bg)
|
||||||
|
{
|
||||||
|
// So we cannot write past fb
|
||||||
|
if (px+FONT_WIDTH > framebuffer->width || py+FONT_HEIGHT > framebuffer->height) return;
|
||||||
|
|
||||||
|
uint8_t* glyph = glyphs + ((unsigned char)c * FONT_HEIGHT);
|
||||||
|
|
||||||
|
for (size_t y=0; y<FONT_HEIGHT; y++)
|
||||||
|
{
|
||||||
|
uint8_t row = glyph[y];
|
||||||
|
for (size_t x=0; x<FONT_WIDTH; x++)
|
||||||
|
{
|
||||||
|
uint32_t color = (row & (0x80 >> x)) ? fg : bg;
|
||||||
|
putpixel(px+x, py+y, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void erase_char(size_t px, size_t py)
|
||||||
|
{
|
||||||
|
if (px+FONT_WIDTH > framebuffer->width || py+FONT_HEIGHT > framebuffer->height) return;
|
||||||
|
|
||||||
|
for (size_t y=0; y<FONT_HEIGHT; y++)
|
||||||
|
{
|
||||||
|
for (size_t x=0; x<FONT_WIDTH; x++)
|
||||||
|
{
|
||||||
|
// Black
|
||||||
|
putpixel(px+x, py+y, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void term_scroll()
|
||||||
|
{
|
||||||
|
// Erase first text line
|
||||||
|
memset(fb, 255, FONT_HEIGHT*framebuffer->pitch);
|
||||||
|
|
||||||
|
// Move whole framebuffer up by one text line
|
||||||
|
memmove(fb, fb+(FONT_HEIGHT*framebuffer->pitch), (framebuffer->height-FONT_HEIGHT)*framebuffer->pitch);
|
||||||
|
|
||||||
|
// Clear last text line
|
||||||
|
size_t clear_start = (framebuffer->height - FONT_HEIGHT) * framebuffer->pitch;
|
||||||
|
memset(fb + clear_start, 255, FONT_HEIGHT * framebuffer->pitch);
|
||||||
|
|
||||||
// Shift line lengths by 1 (for backspace handling)
|
// Shift line lengths by 1 (for backspace handling)
|
||||||
size_t max_lines = term_max_lines();
|
size_t max_lines = term_max_lines();
|
||||||
@@ -119,73 +130,63 @@ void term_scroll()
|
|||||||
{
|
{
|
||||||
lines_length[i - 1] = lines_length[i];
|
lines_length[i - 1] = lines_length[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
lines_length[max_lines - 1] = 0;
|
lines_length[max_lines - 1] = 0;
|
||||||
|
|
||||||
if (cursor.y > 0)
|
|
||||||
{
|
|
||||||
cursor.y--;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void putchar(char c)
|
void putchar(char c)
|
||||||
{
|
{
|
||||||
if ((c == '\n') && ((cursor.y+1)*FONT_HEIGHT >= framebuffer->height))
|
const size_t max_cols = term_max_cols();
|
||||||
{
|
const size_t max_lines = term_max_lines();
|
||||||
term_scroll();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == '\n')
|
if (c == '\n') {
|
||||||
{
|
|
||||||
lines_length[cursor.y] = cursor.x;
|
lines_length[cursor.y] = cursor.x;
|
||||||
cursor.x = 0;
|
cursor.x = 0;
|
||||||
cursor.y++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Improperly handled.
|
if (cursor.y + 1 >= max_lines)
|
||||||
// When we're on an empty line it should get to the upper line's last character
|
|
||||||
// NOT just the last position possible; we would need to track the last line's character amount for that
|
|
||||||
if (c == '\b')
|
|
||||||
{
|
|
||||||
if (cursor.x == 0 && cursor.y == 0)
|
|
||||||
{
|
|
||||||
// Top-left corner
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cursor.x == 0)
|
|
||||||
{
|
|
||||||
cursor.y--;
|
|
||||||
// cursor.x = (framebuffer->width / FONT_WIDTH) -1; // here
|
|
||||||
cursor.x = lines_length[cursor.y];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cursor.x--;
|
|
||||||
}
|
|
||||||
|
|
||||||
int px = cursor.x * FONT_WIDTH;
|
|
||||||
int py = cursor.y * FONT_HEIGHT;
|
|
||||||
erase_char(px, py);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((cursor.x+1)*FONT_WIDTH >= framebuffer->width)
|
|
||||||
{
|
|
||||||
cursor.x = 0;
|
|
||||||
cursor.y++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((cursor.y+1)*FONT_HEIGHT >= framebuffer->height)
|
|
||||||
{
|
{
|
||||||
term_scroll();
|
term_scroll();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cursor.y++;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int px = cursor.x * FONT_WIDTH;
|
if (c == '\b')
|
||||||
int py = cursor.y * FONT_HEIGHT;
|
{
|
||||||
draw_char(c, px, py, WHITE, BLACK);
|
if (cursor.x > 0)
|
||||||
|
{
|
||||||
|
cursor.x--;
|
||||||
|
}
|
||||||
|
else if (cursor.y > 0)
|
||||||
|
{
|
||||||
|
cursor.y--;
|
||||||
|
cursor.x = lines_length[cursor.y];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
erase_char(cursor.x * FONT_WIDTH, cursor.y * FONT_HEIGHT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor.x >= max_cols)
|
||||||
|
{
|
||||||
|
cursor.x = 0;
|
||||||
|
if (cursor.y + 1 >= max_lines)
|
||||||
|
{
|
||||||
|
term_scroll();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cursor.y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_char(c, cursor.x * FONT_WIDTH, cursor.y * FONT_HEIGHT, WHITE, BLACK);
|
||||||
cursor.x++;
|
cursor.x++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +199,7 @@ void _putchar(char character)
|
|||||||
// Debug-printing
|
// Debug-printing
|
||||||
void kputs(const char* str)
|
void kputs(const char* str)
|
||||||
{
|
{
|
||||||
unsigned int i=0;
|
size_t i=0;
|
||||||
while (str[i] != 0)
|
while (str[i] != 0)
|
||||||
{
|
{
|
||||||
putchar(str[i]);
|
putchar(str[i]);
|
||||||
|
|||||||
@@ -22,4 +22,7 @@ typedef struct
|
|||||||
uint8_t characterSize; // height
|
uint8_t characterSize; // height
|
||||||
} PSF1_Header;
|
} PSF1_Header;
|
||||||
|
|
||||||
|
// debug
|
||||||
|
void term_scroll();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -118,11 +118,11 @@ void kmain()
|
|||||||
term_init();
|
term_init();
|
||||||
kputs(splash);
|
kputs(splash);
|
||||||
|
|
||||||
for (int i=0; i<50; i++)
|
for (int i=0; i<10; i++)
|
||||||
{
|
{
|
||||||
printf("testing, attention please %d\n", i);
|
printf("testing, attention please %d\n", i);
|
||||||
timer_wait(1000);
|
|
||||||
}
|
}
|
||||||
|
// term_scroll();
|
||||||
|
|
||||||
hcf();
|
hcf();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ void pic_enable()
|
|||||||
// Enabling IRQ0 (unmasking it) but not the others
|
// Enabling IRQ0 (unmasking it) but not the others
|
||||||
uint8_t mask = inb(0x21);
|
uint8_t mask = inb(0x21);
|
||||||
mask &= ~(1 << 0); // Set IRQ0 (timer, clear bit 0)
|
mask &= ~(1 << 0); // Set IRQ0 (timer, clear bit 0)
|
||||||
mask &= ~(1 << 1); // Set IRQ1 (PS/2 Keyboard, clear bit 1)
|
//mask &= ~(1 << 1); // Set IRQ1 (PS/2 Keyboard, clear bit 1)
|
||||||
outb(0x21, mask);
|
outb(0x21, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user