void hal_uart_init(void);
void hal_uart_putc(char c);
int hal_uart_try_getc(void);
+void hal_uart_set_rx_callback(void (*cb)(char));
#endif
}
menuentry "AdrOS (x86) - ring3 test" {
- multiboot2 /boot/adros-x86.bin ring3
+ multiboot2 /boot/adros-x86.bin ring3 console=serial
+ module2 /boot/initrd.img
+ boot
+}
+
+menuentry "AdrOS (x86) - shell" {
+ multiboot2 /boot/adros-x86.bin init=/bin/sh
module2 /boot/initrd.img
boot
}
/* Route ISA IRQs through IOAPIC:
* IRQ 0 (PIT/Timer) -> IDT vector 32
* IRQ 1 (Keyboard) -> IDT vector 33
+ * IRQ 4 (COM1 UART) -> IDT vector 36
* IRQ 11 (E1000 NIC) -> IDT vector 43
* IRQ 14 (ATA primary) -> IDT vector 46
* IRQ 15 (ATA secondary) -> IDT vector 47 */
ioapic_route_irq(0, 32, (uint8_t)bsp_id);
ioapic_route_irq(1, 33, (uint8_t)bsp_id);
+ ioapic_route_irq(4, 36, (uint8_t)bsp_id); /* COM1 serial */
ioapic_route_irq_level(11, 43, (uint8_t)bsp_id); /* E1000 NIC (PCI: level-triggered, active-low) */
ioapic_route_irq(14, 46, (uint8_t)bsp_id); /* ATA primary */
ioapic_route_irq(15, 47, (uint8_t)bsp_id); /* ATA secondary */
.long multiboot_header_end - multiboot_header_start
.long 0x100000000 - (MB_MAGIC + MB_ARCH + (multiboot_header_end - multiboot_header_start))
- /* Framebuffer request tag (type 5, optional) */
- .align 8
-fb_tag_start:
- .word 5 /* type: framebuffer */
- .word 1 /* flags: optional (boot even if unavailable) */
- .long fb_tag_end - fb_tag_start
- .long 1024 /* preferred width */
- .long 768 /* preferred height */
- .long 32 /* preferred depth (bpp) */
-fb_tag_end:
-
/* End tag */
.align 8
.word 0, 0
}
return -1;
}
+
+void hal_uart_set_rx_callback(void (*cb)(char)) {
+ (void)cb;
+}
}
return -1;
}
+
+void hal_uart_set_rx_callback(void (*cb)(char)) {
+ (void)cb;
+}
}
return -1;
}
+
+void hal_uart_set_rx_callback(void (*cb)(char)) {
+ (void)cb;
+}
#include "hal/uart.h"
#include "io.h"
+#include "arch/x86/idt.h"
#include <stdint.h>
#define UART_BASE 0x3F8
+static void (*uart_rx_cb)(char) = 0;
+
+static void uart_irq_handler(struct registers* regs) {
+ (void)regs;
+ while (inb(UART_BASE + 5) & 0x01) {
+ char c = (char)inb(UART_BASE);
+ if (uart_rx_cb) uart_rx_cb(c);
+ }
+}
+
void hal_uart_init(void) {
+ outb(UART_BASE + 1, 0x00); /* Disable all interrupts */
+ outb(UART_BASE + 3, 0x80); /* Enable DLAB */
+ outb(UART_BASE + 0, 0x03); /* Baud 38400 */
outb(UART_BASE + 1, 0x00);
- outb(UART_BASE + 3, 0x80);
- outb(UART_BASE + 0, 0x03);
- outb(UART_BASE + 1, 0x00);
- outb(UART_BASE + 3, 0x03);
- outb(UART_BASE + 2, 0xC7);
- outb(UART_BASE + 4, 0x0B);
+ outb(UART_BASE + 3, 0x03); /* 8N1 */
+ outb(UART_BASE + 2, 0xC7); /* Enable FIFO */
+ outb(UART_BASE + 4, 0x0B); /* DTR + RTS + OUT2 */
+
+ /* Register IRQ 4 handler (IDT vector 36 = 32 + 4) */
+ register_interrupt_handler(36, uart_irq_handler);
+
+ /* Enable receive data available interrupt (IER bit 0) */
+ outb(UART_BASE + 1, 0x01);
+}
+
+void hal_uart_set_rx_callback(void (*cb)(char)) {
+ uart_rx_cb = cb;
}
void hal_uart_putc(char c) {
/* ---- Static storage ---- */
-static char raw_copy[CMDLINE_MAX];
+static char raw_copy[CMDLINE_MAX]; /* pristine copy for /proc/cmdline */
+static char tok_copy[CMDLINE_MAX]; /* tokenized copy — pointers live here */
/* Kernel-recognized "key=value" parameters */
#define KPARAM_MAX 16
struct kparam {
const char* key;
- const char* value; /* points into raw_copy */
+ const char* value; /* points into tok_copy */
};
static struct kparam kparams[KPARAM_MAX];
strncpy(raw_copy, raw, CMDLINE_MAX - 1);
raw_copy[CMDLINE_MAX - 1] = '\0';
- /* We'll tokenize a second working copy in-place.
- * We can reuse raw_copy since we split by replacing ' ' with '\0'. */
- char work[CMDLINE_MAX];
- strncpy(work, raw_copy, CMDLINE_MAX - 1);
- work[CMDLINE_MAX - 1] = '\0';
+ /* Tokenize a second copy in-place — all pointers will live here */
+ strncpy(tok_copy, raw, CMDLINE_MAX - 1);
+ tok_copy[CMDLINE_MAX - 1] = '\0';
char* tokens[128];
int ntokens = 0;
/* Tokenize by whitespace */
- char* p = work;
+ char* p = tok_copy;
while (*p && ntokens < 128) {
while (*p == ' ' || *p == '\t') p++;
if (!*p) break;
/* "key=value" form */
size_t keylen = (size_t)(eq - tok);
if (is_known_kv_key(tok, keylen)) {
- /* Kernel param: store in raw_copy so pointers remain valid */
- size_t off = (size_t)(tok - work);
if (kparam_count < KPARAM_MAX) {
- /* Point key/value into raw_copy */
- raw_copy[off + keylen] = '\0'; /* split at '=' */
- kparams[kparam_count].key = &raw_copy[off];
- kparams[kparam_count].value = &raw_copy[off + keylen + 1];
+ /* Split "key=value" in tok_copy at '=' */
+ char* eq_ptr = (char*)(uintptr_t)eq;
+ *eq_ptr = '\0';
+ kparams[kparam_count].key = tok;
+ kparams[kparam_count].value = eq_ptr + 1;
kparam_count++;
}
} else {
/* Unrecognized key=value → init envp */
if (init_envc < CMDLINE_MAX_ENVS) {
- size_t off = (size_t)(tok - work);
- init_envp[init_envc++] = &raw_copy[off];
+ init_envp[init_envc++] = tok;
}
}
} else {
/* Plain token (no '=') */
if (is_known_flag(tok)) {
if (kflag_count < KFLAG_MAX) {
- size_t off = (size_t)(tok - work);
- kflags[kflag_count++] = &raw_copy[off];
+ kflags[kflag_count++] = tok;
}
} else if (!has_char(tok, '.')) {
/* No '.' and not recognized → init argv */
if (init_argc < CMDLINE_MAX_ARGS) {
- size_t off = (size_t)(tok - work);
- init_argv[init_argc++] = &raw_copy[off];
+ init_argv[init_argc++] = tok;
}
}
/* Tokens with '.' but no '=' (like module params) are
/* After "--": everything goes to init */
if (eq) {
if (init_envc < CMDLINE_MAX_ENVS) {
- size_t off = (size_t)(tok - work);
- init_envp[init_envc++] = &raw_copy[off];
+ init_envp[init_envc++] = tok;
}
} else {
if (init_argc < CMDLINE_MAX_ARGS) {
- size_t off = (size_t)(tok - work);
- init_argv[init_argc++] = &raw_copy[off];
+ init_argv[init_argc++] = tok;
}
}
}
#include "errno.h"
#include "hal/cpu.h"
+#include "hal/uart.h"
#include "utils.h"
#define TTY_LINE_MAX 256
tty_fg_pgrp = 0;
keyboard_set_callback(tty_keyboard_cb);
+ hal_uart_set_rx_callback(tty_input_char);
static const struct file_operations tty_fops = {
.read = tty_devfs_read,