Feat: Keyboard strokes working and in buffer
This commit is contained in:
+8
-31
@@ -1,6 +1,10 @@
|
|||||||
; File: elevator.asm
|
; File: elevator.asm
|
||||||
; Stage 2 Bootloader - No size limit!
|
; Stage 2 Bootloader - No size limit!
|
||||||
; Job: Load kernel, set up GDT, switch to 64-bit mode, jump to kernel
|
; Job: Load kernel, set up GDT, switch to 64-bit mode, jump to kernel
|
||||||
|
%ifndef KERNEL_SECTORS
|
||||||
|
%define KERNEL_SECTORS 10 ; fallback default if build.sh doesn't override it
|
||||||
|
%endif
|
||||||
|
|
||||||
[org 0x7e00]
|
[org 0x7e00]
|
||||||
[bits 16]
|
[bits 16]
|
||||||
|
|
||||||
@@ -104,7 +108,7 @@ load_kernel:
|
|||||||
|
|
||||||
; Set up DAP (Disk Address Packet)
|
; Set up DAP (Disk Address Packet)
|
||||||
mov word [dap_size], 0x10
|
mov word [dap_size], 0x10
|
||||||
mov word [dap_sectors], 10
|
mov word [dap_sectors], KERNEL_SECTORS
|
||||||
mov word [dap_offset], 0x0000
|
mov word [dap_offset], 0x0000
|
||||||
mov word [dap_segment], 0x1000
|
mov word [dap_segment], 0x1000
|
||||||
mov dword [dap_lba_low], 6 ; LBA 6 = bytes 3072+ (sector 7 in CHS)
|
mov dword [dap_lba_low], 6 ; LBA 6 = bytes 3072+ (sector 7 in CHS)
|
||||||
@@ -136,7 +140,7 @@ load_kernel:
|
|||||||
|
|
||||||
; Read using CHS
|
; Read using CHS
|
||||||
mov ah, 0x02 ; Read function
|
mov ah, 0x02 ; Read function
|
||||||
mov al, 10 ; Number of sectors
|
mov al, KERNEL_SECTORS ; Number of sectors
|
||||||
mov ch, 0 ; Cylinder 0
|
mov ch, 0 ; Cylinder 0
|
||||||
mov cl, 7 ; Sector 7
|
mov cl, 7 ; Sector 7
|
||||||
mov dh, 0 ; Head 0
|
mov dh, 0 ; Head 0
|
||||||
@@ -490,7 +494,6 @@ pm_msg: db '[PM32] Setting up Long Mode...', 0
|
|||||||
; 64-BIT LONG MODE
|
; 64-BIT LONG MODE
|
||||||
; ============================================================
|
; ============================================================
|
||||||
[bits 64]
|
[bits 64]
|
||||||
[extern __keyboard_buffer_push] ; External function to push key into keyboard buffer
|
|
||||||
long_mode:
|
long_mode:
|
||||||
; Set up segments
|
; Set up segments
|
||||||
mov ax, 0x20
|
mov ax, 0x20
|
||||||
@@ -518,8 +521,6 @@ long_mode:
|
|||||||
mov rsi, before_kernel_msg
|
mov rsi, before_kernel_msg
|
||||||
call print_64
|
call print_64
|
||||||
|
|
||||||
sti ; Enable interrupts before jumping to kernel
|
|
||||||
|
|
||||||
; JUMP TO KERNEL!
|
; JUMP TO KERNEL!
|
||||||
call KERNEL_OFFSET
|
call KERNEL_OFFSET
|
||||||
|
|
||||||
@@ -624,32 +625,6 @@ setup_pic:
|
|||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; keyboard handler - Catch PIC interrupt
|
|
||||||
keyboard_handler:
|
|
||||||
push rax
|
|
||||||
push rdx
|
|
||||||
push rdi
|
|
||||||
push r8
|
|
||||||
|
|
||||||
mov dx, 0x60
|
|
||||||
in al, dx
|
|
||||||
|
|
||||||
; convert ASCII
|
|
||||||
; assuming output on r8 (as an example)
|
|
||||||
|
|
||||||
; Acording to x86_64 SystemV
|
|
||||||
mov rdi, r8
|
|
||||||
call __keyboard_buffer_push
|
|
||||||
|
|
||||||
mov al, 0x20
|
|
||||||
out 0x20, al
|
|
||||||
|
|
||||||
pop r8
|
|
||||||
pop rdi
|
|
||||||
pop rdx
|
|
||||||
pop rax
|
|
||||||
iretq
|
|
||||||
|
|
||||||
; Exception handler - shows what went wrong
|
; Exception handler - shows what went wrong
|
||||||
exception_handler:
|
exception_handler:
|
||||||
; Save registers
|
; Save registers
|
||||||
@@ -707,6 +682,8 @@ exception_handler:
|
|||||||
|
|
||||||
; Dummy interrupt handler for IRQs (not CPU exceptions)
|
; Dummy interrupt handler for IRQs (not CPU exceptions)
|
||||||
dummy_handler:
|
dummy_handler:
|
||||||
|
mov al, 0x20
|
||||||
|
out 0x20, al ; Send EOI to PIC
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
idt_descriptor:
|
idt_descriptor:
|
||||||
|
|||||||
@@ -2,14 +2,79 @@
|
|||||||
; Assembly entry point for the kernel
|
; Assembly entry point for the kernel
|
||||||
[bits 64]
|
[bits 64]
|
||||||
[extern kmain] ; kmain is defined in kernel.c
|
[extern kmain] ; kmain is defined in kernel.c
|
||||||
|
[extern __keyboard_handle_scancode]
|
||||||
|
[extern __bss_start]
|
||||||
|
[extern __bss_end]
|
||||||
|
|
||||||
global _start ; Make _start visible to linker
|
global _start ; Make _start visible to linker
|
||||||
|
|
||||||
_start:
|
_start:
|
||||||
|
call fill_idt
|
||||||
|
|
||||||
|
; IMPORTANT
|
||||||
|
; Zero out the .bss section
|
||||||
|
cld
|
||||||
|
mov rdi, __bss_start
|
||||||
|
mov rcx, __bss_end
|
||||||
|
sub rcx, rdi
|
||||||
|
xor rax, rax
|
||||||
|
rep stosb
|
||||||
|
|
||||||
; We're already in 64-bit mode with stack set up
|
; We're already in 64-bit mode with stack set up
|
||||||
; Just call the C kernel
|
; Just call the C kernel
|
||||||
|
sti
|
||||||
call kmain
|
call kmain
|
||||||
|
|
||||||
; If kmain returns, hang
|
; If kmain returns, hang
|
||||||
jmp $
|
jmp $
|
||||||
|
hlt
|
||||||
|
|
||||||
|
|
||||||
|
; Set up a minimal IDT
|
||||||
|
fill_idt:
|
||||||
|
; Fill IDT with different handlers for different exceptions
|
||||||
|
mov rdi, 0x4210 ; IDT location
|
||||||
|
mov rax, keyboard_handler
|
||||||
|
|
||||||
|
mov word [rdi], ax ; Offset low
|
||||||
|
mov word [rdi + 2], 0x18 ; Code segment
|
||||||
|
mov byte [rdi + 4], 0 ; IST
|
||||||
|
mov byte [rdi + 5], 0x8E ; Present, interrupt gate
|
||||||
|
shr rax, 16
|
||||||
|
mov word [rdi + 6], ax ; Offset middle
|
||||||
|
shr rax, 16
|
||||||
|
mov dword [rdi + 8], eax ; Offset high
|
||||||
|
mov dword [rdi + 12], 0 ; Reserved
|
||||||
|
ret
|
||||||
|
|
||||||
|
; keyboard handler - Catch PIC interrupt
|
||||||
|
keyboard_handler:
|
||||||
|
push rax
|
||||||
|
push rdx
|
||||||
|
push rdi
|
||||||
|
push rcx
|
||||||
|
push rsi
|
||||||
|
push r8
|
||||||
|
push r9
|
||||||
|
push r10
|
||||||
|
push r11
|
||||||
|
|
||||||
|
mov dx, 0x60
|
||||||
|
in al, dx
|
||||||
|
|
||||||
|
mov dil, al
|
||||||
|
call __keyboard_handle_scancode
|
||||||
|
|
||||||
|
mov al, 0x20
|
||||||
|
out 0x20, al
|
||||||
|
|
||||||
|
pop r11
|
||||||
|
pop r10
|
||||||
|
pop r9
|
||||||
|
pop r8
|
||||||
|
pop rsi
|
||||||
|
pop rcx
|
||||||
|
pop rdi
|
||||||
|
pop rdx
|
||||||
|
pop rax
|
||||||
|
iretq
|
||||||
|
|||||||
@@ -24,22 +24,27 @@ echo -e "${GREEN}✓${NC} Folders created.${NC}"
|
|||||||
echo -e "${BLUE}[1/6]${NC} Assembling Stage 1 bootloader (MBR)..."
|
echo -e "${BLUE}[1/6]${NC} Assembling Stage 1 bootloader (MBR)..."
|
||||||
nasm -f bin ./boot/boot.asm -o ./bin/boot.bin
|
nasm -f bin ./boot/boot.asm -o ./bin/boot.bin
|
||||||
|
|
||||||
# Step 2: Assemble Stage 2 bootloader (extended loader)
|
# Step 2: Compile kernel C code
|
||||||
echo -e "${BLUE}[2/6]${NC} Assembling Stage 2 bootloader..."
|
echo -e "${BLUE}[2/6]${NC} Compiling kernel..."
|
||||||
nasm -f bin ./boot/elevator.asm -o ./bin/elevator.bin
|
gcc -ffreestanding -c kernel.c -o ./obj/kernel.c.o -mcmodel=large -mno-red-zone -fno-pic -fno-pie -static -fno-stack-protector -nostdlib -mno-mmx -mno-sse -mno-sse2 -m64
|
||||||
|
|
||||||
# Step 3: Assemble kernel entry point
|
# Step 3: Assemble kernel entry point
|
||||||
echo -e "${BLUE}[3/6]${NC} Assembling kernel entry..."
|
echo -e "${BLUE}[3/6]${NC} Assembling kernel entry..."
|
||||||
nasm -f elf64 ./boot/kernel.asm -o ./obj/kernel.asm.o
|
nasm -f elf64 ./boot/kernel.asm -o ./obj/kernel.asm.o
|
||||||
|
|
||||||
# Step 4: Compile kernel C code
|
# Step 4: Link kernel
|
||||||
echo -e "${BLUE}[4/6]${NC} Compiling kernel..."
|
echo -e "${BLUE}[4/6]${NC} Linking kernel..."
|
||||||
gcc -ffreestanding -c kernel.c -o ./obj/kernel.c.o -mcmodel=large -mno-red-zone -fno-pic -fno-pie -static -fno-stack-protector -nostdlib -mno-mmx -mno-sse -mno-sse2 -m64
|
|
||||||
|
|
||||||
# Step 5: Link kernel
|
|
||||||
echo -e "${BLUE}[5/6]${NC} Linking kernel..."
|
|
||||||
ld -T linker.ld -o ./bin/kernel.bin ./obj/kernel.asm.o ./obj/kernel.c.o --oformat binary --nostdlib
|
ld -T linker.ld -o ./bin/kernel.bin ./obj/kernel.asm.o ./obj/kernel.c.o --oformat binary --nostdlib
|
||||||
|
|
||||||
|
# Step 4.5: Calculate kernel size in sectors
|
||||||
|
KERNEL_SIZE=$(stat -f%z ./bin/kernel.bin 2>/dev/null || stat -c%s ./bin/kernel.bin 2>/dev/null)
|
||||||
|
SECTORS=$(( (KERNEL_SIZE + 511) / 512 )) #Round up to nearest sector
|
||||||
|
echo -e "${YELLOW}Kernel size: ${KERNEL_SIZE} bytes, which is ${SECTORS} sectors.${NC}"
|
||||||
|
|
||||||
|
# Step 5: Assemble Stage 2 bootloader (extended loader)
|
||||||
|
echo -e "${BLUE}[5/6]${NC} Assembling Stage 2 bootloader..."
|
||||||
|
nasm -f bin ./boot/elevator.asm -D KERNEL_SECTORS=$SECTORS -o ./bin/elevator.bin
|
||||||
|
|
||||||
# Step 6: Create OS image
|
# Step 6: Create OS image
|
||||||
echo -e "${BLUE}[6/6]${NC} Creating OS image..."
|
echo -e "${BLUE}[6/6]${NC} Creating OS image..."
|
||||||
cat ./bin/boot.bin ./bin/elevator.bin ./bin/kernel.bin > os.bin
|
cat ./bin/boot.bin ./bin/elevator.bin ./bin/kernel.bin > os.bin
|
||||||
|
|||||||
@@ -25,16 +25,21 @@ void kmain(void) {
|
|||||||
printf("SoraOS Kernel Initialized\n");
|
printf("SoraOS Kernel Initialized\n");
|
||||||
printf("\tWelcome to SoraOS\n");
|
printf("\tWelcome to SoraOS\n");
|
||||||
printf("\tKernel Version %s\n", __KERNEL_VERSION);
|
printf("\tKernel Version %s\n", __KERNEL_VERSION);
|
||||||
// printf("\tCompiled on: %s at %s\n\n", __DATE__, __TIME__);
|
printf("\tCompiled on: %s at %s\n\n", __DATE__, __TIME__);
|
||||||
|
|
||||||
// TODO: CLI IDEA
|
// TODO: CLI IDEA
|
||||||
// int _count = printf("%s@%s:>", current_user.user_name, current_user.user_hostname);
|
int _count = printf("%s@%s:>", current_user.user_name, current_user.user_hostname);
|
||||||
// scursor(_count, text_pos.line);
|
//scursor(_count, text_pos.line);
|
||||||
|
|
||||||
// TODO: Enable user input handling
|
// TODO: Enable user input handling
|
||||||
// char input_buffer[256];
|
char input_buffer[256] = {0};
|
||||||
// scanf("%s", input_buffer);
|
gets(input_buffer, sizeof(input_buffer));
|
||||||
// printf("\nYou entered: %s\n", input_buffer);
|
|
||||||
|
printf("Input buffer contents in hex:\n");
|
||||||
|
for (int i = 0; input_buffer[i] != '\0'; i++) {
|
||||||
|
printf("[%x]", (unsigned char)input_buffer[i]);
|
||||||
|
}
|
||||||
|
printf("\nYou entered: %s\n", input_buffer);
|
||||||
|
|
||||||
// Infinite loop
|
// Infinite loop
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|||||||
@@ -20,7 +20,11 @@ SECTIONS
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
|
__bss_start = .;
|
||||||
|
|
||||||
*(.bss)
|
*(.bss)
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
|
|
||||||
|
__bss_end = .;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define VGA_WIDTH 80
|
#define VGA_WIDTH 80
|
||||||
#define VGA_HEIGHT 25
|
#define VGA_HEIGHT 25
|
||||||
@@ -21,9 +22,9 @@
|
|||||||
#define SCANCODE_CAPSLOCK 0x3A
|
#define SCANCODE_CAPSLOCK 0x3A
|
||||||
#define RELEASE_MASK 0x80
|
#define RELEASE_MASK 0x80
|
||||||
|
|
||||||
static char _keyboard_buffer[KEYBOARD_BUFFER_SIZE];
|
static volatile unsigned char _keyboard_buffer[KEYBOARD_BUFFER_SIZE];
|
||||||
static uint16_t _kb_head = 0;
|
static volatile uint16_t _kb_head = 0;
|
||||||
static uint16_t _kb_tail = 0;
|
static volatile uint16_t _kb_tail = 0;
|
||||||
|
|
||||||
static char __g_shift_pressed = 0;
|
static char __g_shift_pressed = 0;
|
||||||
static char __g_caps_lock_active = 0;
|
static char __g_caps_lock_active = 0;
|
||||||
@@ -396,7 +397,7 @@ static inline char __keyboard_buffer_pop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline char __convert_ascii(uint8_t __scancode) {
|
static inline char __convert_ascii(uint8_t __scancode) {
|
||||||
char __code = __scancode & ~RELEASE_MASK;
|
unsigned char __code = __scancode & ~RELEASE_MASK;
|
||||||
if (__scancode & 0x80) {
|
if (__scancode & 0x80) {
|
||||||
// Key-released
|
// Key-released
|
||||||
if (__code == SCANCODE_LSHIFT || __code == SCANCODE_RSHIFT) {
|
if (__code == SCANCODE_LSHIFT || __code == SCANCODE_RSHIFT) {
|
||||||
@@ -434,14 +435,63 @@ static inline char __convert_ascii(uint8_t __scancode) {
|
|||||||
return __char;
|
return __char;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t __scancode_h[128] = {0};
|
||||||
|
static uint32_t __total_isr_calls = 0;
|
||||||
|
|
||||||
void __keyboard_handle_scancode(uint8_t __scancode) {
|
void __keyboard_handle_scancode(uint8_t __scancode) {
|
||||||
|
__total_isr_calls++;
|
||||||
|
|
||||||
char __temp = __convert_ascii(__scancode);
|
char __temp = __convert_ascii(__scancode);
|
||||||
|
static uint8_t __index = 0;
|
||||||
|
|
||||||
|
if (__index < sizeof(__scancode_h)) {
|
||||||
|
__scancode_h[__index++] = __scancode;
|
||||||
|
}
|
||||||
|
|
||||||
if (__temp == '\0') {
|
if (__temp == '\0') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
__keyboard_buffer_push(__temp);
|
__keyboard_buffer_push(__temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __dump_scancode_history() {
|
||||||
|
printf("Scancode History: \n");
|
||||||
|
printf("Total ISR Calls: %u\n", __total_isr_calls);
|
||||||
|
for (size_t i = 0; i < sizeof(__scancode_h); i++) {
|
||||||
|
if (__scancode_h[i] != 0) {
|
||||||
|
printf("[%x] = %c\n", __scancode_h[i], __convert_ascii(__scancode_h[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char __gets_internal(char *buffer, size_t max_length) {
|
||||||
|
size_t index = 0;
|
||||||
|
char __c;
|
||||||
|
|
||||||
|
while (index < max_length - 1) {
|
||||||
|
__c = __keyboard_buffer_pop();
|
||||||
|
|
||||||
|
if (__c == '\0') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__c == '\n' || __c == '\r') {
|
||||||
|
buffer[index] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[index++] = __c;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[index] = '\0';
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gets(char *buffer, size_t max_length) {
|
||||||
|
__gets_internal(buffer, max_length);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
static inline int __scanf_internal(const char *fmt, va_list args) {
|
static inline int __scanf_internal(const char *fmt, va_list args) {
|
||||||
|
|
||||||
@@ -509,7 +559,6 @@ int scanf(const char *fmt, ...) {
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user