kernel: add basic console registration system and printk()
This commit is contained in:
@@ -1,7 +0,0 @@
|
|||||||
#ifndef SOCKS_X86_64_CONSOLE_H_
|
|
||||||
#define SOCKS_X86_64_CONSOLE_H_
|
|
||||||
|
|
||||||
extern void ml_console_init(void);
|
|
||||||
extern void ml_console_putchar(int c);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <socks/machine/_gdt.h>
|
#include <socks/machine/_gdt.h>
|
||||||
|
|
||||||
|
#define ml_halt_cpu() asm volatile("cli;hlt")
|
||||||
|
|
||||||
typedef struct ml_cpu_block {
|
typedef struct ml_cpu_block {
|
||||||
struct gdt c_gdt;
|
struct gdt c_gdt;
|
||||||
struct gdt_ptr c_gdt_ptr;
|
struct gdt_ptr c_gdt_ptr;
|
||||||
|
|||||||
6
arch/x86_64/include/socks/machine/vgacon.h
Normal file
6
arch/x86_64/include/socks/machine/vgacon.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef SOCKS_X86_64_CONSOLE_H_
|
||||||
|
#define SOCKS_X86_64_CONSOLE_H_
|
||||||
|
|
||||||
|
extern void vgacon_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <socks/machine/cpu.h>
|
#include <socks/machine/cpu.h>
|
||||||
|
#include <socks/machine/vgacon.h>
|
||||||
|
|
||||||
static ml_cpu_block g_bootstrap_cpu = {0};
|
static ml_cpu_block g_bootstrap_cpu = {0};
|
||||||
|
|
||||||
@@ -11,5 +12,6 @@ static void bootstrap_cpu_init(void)
|
|||||||
int ml_init(uintptr_t arg)
|
int ml_init(uintptr_t arg)
|
||||||
{
|
{
|
||||||
bootstrap_cpu_init();
|
bootstrap_cpu_init();
|
||||||
|
vgacon_init();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include <socks/libc/string.h>
|
#include <socks/libc/string.h>
|
||||||
#include <socks/libc/ctype.h>
|
#include <socks/libc/ctype.h>
|
||||||
#include <socks/machine/ports.h>
|
#include <socks/machine/ports.h>
|
||||||
|
#include <socks/console.h>
|
||||||
|
#include <socks/printk.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define VGA_PORT_CMD 0x3D4
|
#define VGA_PORT_CMD 0x3D4
|
||||||
@@ -36,15 +38,6 @@ static void move_vga_cursor(unsigned int x, unsigned int y)
|
|||||||
outportb(VGA_PORT_DATA, (uint8_t)((offset >> 8) & 0xFF));
|
outportb(VGA_PORT_DATA, (uint8_t)((offset >> 8) & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ml_console_init(void)
|
|
||||||
{
|
|
||||||
g_console_cursor_xpos = 0;
|
|
||||||
g_console_cursor_ypos = 5;
|
|
||||||
|
|
||||||
init_vga_cursor();
|
|
||||||
move_vga_cursor(g_console_cursor_xpos, g_console_cursor_ypos);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void scroll_display()
|
static void scroll_display()
|
||||||
{
|
{
|
||||||
uint16_t *src = g_console_fb + k_console_width;
|
uint16_t *src = g_console_fb + k_console_width;
|
||||||
@@ -79,7 +72,7 @@ static void handle_ctrl(int c)
|
|||||||
move_vga_cursor(g_console_cursor_xpos, g_console_cursor_ypos);
|
move_vga_cursor(g_console_cursor_xpos, g_console_cursor_ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ml_console_putchar(int c)
|
static void vgacon_putchar(int c)
|
||||||
{
|
{
|
||||||
if (iscntrl(c)) {
|
if (iscntrl(c)) {
|
||||||
handle_ctrl(c);
|
handle_ctrl(c);
|
||||||
@@ -103,3 +96,29 @@ void ml_console_putchar(int c)
|
|||||||
|
|
||||||
move_vga_cursor(g_console_cursor_xpos, g_console_cursor_ypos);
|
move_vga_cursor(g_console_cursor_xpos, g_console_cursor_ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vgacon_write(console_t *con, const char *s, unsigned int len)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < len; i++) {
|
||||||
|
vgacon_putchar(s[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static console_t vgacon = {
|
||||||
|
.c_name = "vgacon",
|
||||||
|
.c_flags = CON_BOOT,
|
||||||
|
.c_write = vgacon_write,
|
||||||
|
.c_lock = SPIN_LOCK_INIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
void vgacon_init(void)
|
||||||
|
{
|
||||||
|
g_console_cursor_xpos = 0;
|
||||||
|
g_console_cursor_ypos = 5;
|
||||||
|
|
||||||
|
init_vga_cursor();
|
||||||
|
move_vga_cursor(g_console_cursor_xpos, g_console_cursor_ypos);
|
||||||
|
|
||||||
|
console_register(&vgacon);
|
||||||
|
early_printk_init(&vgacon);
|
||||||
|
}
|
||||||
@@ -1,7 +1,29 @@
|
|||||||
#ifndef SOCKS_CONSOLE_H_
|
#ifndef SOCKS_CONSOLE_H_
|
||||||
#define SOCKS_CONSOLE_H_
|
#define SOCKS_CONSOLE_H_
|
||||||
|
|
||||||
extern void console_init(void);
|
#include <socks/queue.h>
|
||||||
extern void console_putchar(int c);
|
#include <socks/locks.h>
|
||||||
|
#include <socks/status.h>
|
||||||
|
|
||||||
|
typedef enum console_flags {
|
||||||
|
CON_BOOT = 0x01u,
|
||||||
|
} console_flags_t;
|
||||||
|
|
||||||
|
typedef struct console {
|
||||||
|
char c_name[16];
|
||||||
|
console_flags_t c_flags;
|
||||||
|
spin_lock_t c_lock;
|
||||||
|
|
||||||
|
void (*c_write)(struct console *, const char *, unsigned int);
|
||||||
|
int (*c_read)(struct console *, char *, unsigned int);
|
||||||
|
|
||||||
|
queue_entry_t c_list;
|
||||||
|
} console_t;
|
||||||
|
|
||||||
|
extern kern_status_t console_register(console_t *con);
|
||||||
|
extern kern_status_t console_unregister(console_t *con);
|
||||||
|
|
||||||
|
extern void console_write(console_t *con, const char *s, unsigned int len);
|
||||||
|
extern int console_read(console_t *con, char *s, unsigned int len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#ifndef SOCKS_PRINTK_H_
|
#ifndef SOCKS_PRINTK_H_
|
||||||
#define SOCKS_PRINTK_H_
|
#define SOCKS_PRINTK_H_
|
||||||
|
|
||||||
|
#include <socks/console.h>
|
||||||
|
|
||||||
|
extern void early_printk_init(console_t *con);
|
||||||
extern int printk(const char *format, ...);
|
extern int printk(const char *format, ...);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
typedef unsigned int kern_status_t;
|
typedef unsigned int kern_status_t;
|
||||||
|
|
||||||
#define KERN_OK (0)
|
#define KERN_OK (0)
|
||||||
#define KERN_ERR_UNIMPLEMENTED (1)
|
#define KERN_UNIMPLEMENTED (1)
|
||||||
|
#define KERN_NAME_EXISTS (2)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,12 +2,15 @@
|
|||||||
#include <socks/init.h>
|
#include <socks/init.h>
|
||||||
#include <socks/printk.h>
|
#include <socks/printk.h>
|
||||||
#include <socks/machine/init.h>
|
#include <socks/machine/init.h>
|
||||||
|
#include <socks/machine/cpu.h>
|
||||||
|
|
||||||
|
extern unsigned long get_rflags(void);
|
||||||
|
|
||||||
void kernel_init(uintptr_t arg)
|
void kernel_init(uintptr_t arg)
|
||||||
{
|
{
|
||||||
ml_init(arg);
|
ml_init(arg);
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
printk("hello, world!");
|
||||||
printk("Line %d\n", i);
|
|
||||||
}
|
ml_halt_cpu();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,52 @@
|
|||||||
#include <socks/console.h>
|
#include <socks/console.h>
|
||||||
#include <socks/machine/console.h>
|
#include <socks/queue.h>
|
||||||
|
#include <socks/locks.h>
|
||||||
|
#include <socks/libc/string.h>
|
||||||
|
|
||||||
void console_init(void)
|
static queue_t consoles;
|
||||||
|
static spin_lock_t consoles_lock = SPIN_LOCK_INIT;
|
||||||
|
|
||||||
|
kern_status_t console_register(console_t *con)
|
||||||
{
|
{
|
||||||
ml_console_init();
|
unsigned long flags;
|
||||||
|
spin_lock_irqsave(&consoles_lock, &flags);
|
||||||
|
|
||||||
|
queue_foreach (console_t, cur, &consoles, c_list) {
|
||||||
|
if (!strcmp(cur->c_name, con->c_name)) {
|
||||||
|
spin_unlock_irqrestore(&consoles_lock, flags);
|
||||||
|
return KERN_NAME_EXISTS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_push_back(&consoles, &con->c_list);
|
||||||
|
spin_unlock_irqrestore(&consoles_lock, flags);
|
||||||
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void console_putchar(int c)
|
kern_status_t console_unregister(console_t *con)
|
||||||
{
|
{
|
||||||
ml_console_putchar(c);
|
unsigned long flags;
|
||||||
|
spin_lock_irqsave(&consoles_lock, &flags);
|
||||||
|
|
||||||
|
queue_delete(&consoles, &con->c_list);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&consoles_lock, flags);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void console_write(console_t *con, const char *s, unsigned int len)
|
||||||
|
{
|
||||||
|
if (con->c_write) {
|
||||||
|
con->c_write(con, s, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int console_read(console_t *con, char *s, unsigned int len)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
if (con->c_read) {
|
||||||
|
ret = con->c_read(con, s, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,74 @@
|
|||||||
|
#include <socks/printk.h>
|
||||||
|
#include <socks/locks.h>
|
||||||
|
#include <socks/console.h>
|
||||||
|
#include <socks/libc/stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#define LOG_BUFFER_SIZE 0x40000
|
#define LOG_BUFFER_SIZE 0x40000
|
||||||
|
#define LOG_MSG_SIZE 0x100
|
||||||
|
|
||||||
|
static console_t *early_console = NULL;
|
||||||
|
|
||||||
|
static spin_lock_t log_buffer_lock = SPIN_LOCK_INIT;
|
||||||
|
|
||||||
static char log_buffer[LOG_BUFFER_SIZE] = {0};
|
static char log_buffer[LOG_BUFFER_SIZE] = {0};
|
||||||
|
/* index of the last character in log_buffer that has been written
|
||||||
|
to the console */
|
||||||
|
static unsigned int log_buffer_readp = 0;
|
||||||
|
/* index of the last character in log_buffer that has been logged
|
||||||
|
(but not necessarily written to the console) */
|
||||||
|
static unsigned int log_buffer_writep = 0;
|
||||||
|
|
||||||
|
static void flush_log_buffer(void)
|
||||||
|
{
|
||||||
|
if (!early_console) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console_write(early_console, log_buffer + log_buffer_readp, log_buffer_writep - log_buffer_readp);
|
||||||
|
log_buffer_readp = log_buffer_writep;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void save_log_message(const char *msg)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
while (1) {
|
||||||
|
if (log_buffer_writep == LOG_BUFFER_SIZE - 1) {
|
||||||
|
log_buffer[log_buffer_writep] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg[i] == '\0') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_buffer[log_buffer_writep++] = msg[i++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void early_printk_init(console_t *con)
|
||||||
|
{
|
||||||
|
early_console = con;
|
||||||
|
}
|
||||||
|
|
||||||
int printk(const char *format, ...)
|
int printk(const char *format, ...)
|
||||||
{
|
{
|
||||||
(void)log_buffer;
|
char msg[LOG_MSG_SIZE];
|
||||||
return 0;
|
|
||||||
|
va_list arg;
|
||||||
|
va_start(arg, format);
|
||||||
|
int len = vsnprintf(msg, sizeof msg - 1, format, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
msg[len] = '\n';
|
||||||
|
msg[len + 1] = '\0';
|
||||||
|
|
||||||
|
unsigned long flags;
|
||||||
|
spin_lock_irqsave(&log_buffer_lock, &flags);
|
||||||
|
save_log_message(msg);
|
||||||
|
spin_unlock_irqrestore(&log_buffer_lock, flags);
|
||||||
|
|
||||||
|
flush_log_buffer();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user