console changes
Signed-off-by: kaguya3311 <kaguya3311@national.shitposting.agency>
This commit is contained in:
@@ -7,3 +7,4 @@ void serial_putchar(char ch);
|
|||||||
void serial_puts(char *str);
|
void serial_puts(char *str);
|
||||||
char serial_get_byte(void);
|
char serial_get_byte(void);
|
||||||
char serial_getchar(void);
|
char serial_getchar(void);
|
||||||
|
int serial_received(void);
|
||||||
+132
-1
@@ -9,6 +9,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "arch/x86_64/serial/serial.h"
|
||||||
|
#include "sched/sched.h"
|
||||||
|
|
||||||
struct console {
|
struct console {
|
||||||
struct resource res;
|
struct resource res;
|
||||||
@@ -19,6 +21,11 @@ struct console {
|
|||||||
|
|
||||||
struct console *console_device = NULL;
|
struct console *console_device = NULL;
|
||||||
|
|
||||||
|
static void console_emit(char c) {
|
||||||
|
framebuffer_putchar(c);
|
||||||
|
serial_putchar(c);
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t console_write(struct resource *this,
|
static ssize_t console_write(struct resource *this,
|
||||||
struct f_description *description, const void *buf,
|
struct f_description *description, const void *buf,
|
||||||
off_t offset, size_t count) {
|
off_t offset, size_t count) {
|
||||||
@@ -34,13 +41,114 @@ static ssize_t console_write(struct resource *this,
|
|||||||
|
|
||||||
char *r = (char *)buf;
|
char *r = (char *)buf;
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
framebuffer_putchar(r[i]);
|
console_emit(r[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
spinlock_drop(&this->lock);
|
spinlock_drop(&this->lock);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t console_read(struct resource *this,
|
||||||
|
struct f_description *description, void *buf,
|
||||||
|
off_t offset, size_t count) {
|
||||||
|
(void)this;
|
||||||
|
(void)description;
|
||||||
|
(void)offset;
|
||||||
|
|
||||||
|
if (!buf) {
|
||||||
|
errno = EFAULT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *out = (char *)buf;
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
tcflag_t lflag = console_device->term.c_lflag;
|
||||||
|
tcflag_t iflag = console_device->term.c_iflag;
|
||||||
|
bool canon = (lflag & ICANON) != 0;
|
||||||
|
bool echo = (lflag & ECHO) != 0;
|
||||||
|
bool echoe = (lflag & ECHOE) != 0;
|
||||||
|
|
||||||
|
cc_t verase = console_device->term.c_cc[VERASE];
|
||||||
|
if (verase == 0) {
|
||||||
|
verase = 0x7f;
|
||||||
|
}
|
||||||
|
cc_t veof = console_device->term.c_cc[VEOF];
|
||||||
|
|
||||||
|
while (pos < count) {
|
||||||
|
while (!serial_received()) {
|
||||||
|
sched_yield(true);
|
||||||
|
}
|
||||||
|
char c = serial_get_byte();
|
||||||
|
|
||||||
|
// Input mode flags
|
||||||
|
if ((iflag & ISTRIP) != 0) {
|
||||||
|
c = (char)((unsigned char)c & 0x7f);
|
||||||
|
}
|
||||||
|
if ((iflag & IGNCR) != 0 && c == '\r') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((iflag & ICRNL) != 0 && c == '\r') {
|
||||||
|
c = '\n';
|
||||||
|
} else if ((iflag & INLCR) != 0 && c == '\n') {
|
||||||
|
c = '\r';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canon) {
|
||||||
|
// Backspace / VERASE handling
|
||||||
|
if (c == (char)verase || c == 0x08) {
|
||||||
|
if (pos > 0) {
|
||||||
|
pos--;
|
||||||
|
if (echo && echoe) {
|
||||||
|
console_emit('\b');
|
||||||
|
console_emit(' ');
|
||||||
|
console_emit('\b');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF: return what we have so far (possibly 0)
|
||||||
|
if (veof != 0 && c == (char)veof) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[pos++] = c;
|
||||||
|
|
||||||
|
if (echo) {
|
||||||
|
if (c == '\n') {
|
||||||
|
console_emit('\n');
|
||||||
|
} else if ((unsigned char)c < 0x20 && c != '\t' &&
|
||||||
|
(lflag & ECHOCTL) != 0) {
|
||||||
|
console_emit('^');
|
||||||
|
console_emit((char)(c + 0x40));
|
||||||
|
} else {
|
||||||
|
console_emit(c);
|
||||||
|
}
|
||||||
|
} else if (c == '\n' && (lflag & ECHONL) != 0) {
|
||||||
|
console_emit('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Non-canonical (raw) mode: return as soon as we have any data.
|
||||||
|
out[pos++] = c;
|
||||||
|
if (echo) {
|
||||||
|
console_emit(c);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ssize_t)pos;
|
||||||
|
}
|
||||||
|
|
||||||
int console_ioctl(struct resource *this, struct f_description *description,
|
int console_ioctl(struct resource *this, struct f_description *description,
|
||||||
uint64_t request, uint64_t arg) {
|
uint64_t request, uint64_t arg) {
|
||||||
(void)description;
|
(void)description;
|
||||||
@@ -76,6 +184,27 @@ int console_ioctl(struct resource *this, struct f_description *description,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case TIOCSWINSZ:
|
||||||
|
// Accept but ignore: the console window size is fixed by the fb.
|
||||||
|
break;
|
||||||
|
case TIOCSCTTY:
|
||||||
|
// Becoming the controlling tty is a no-op; there's only one console
|
||||||
|
// and any process opening it is implicitly attached.
|
||||||
|
break;
|
||||||
|
case TIOCGPGRP:
|
||||||
|
case TIOCGSID: {
|
||||||
|
int *n = (int *)arg;
|
||||||
|
if (n) {
|
||||||
|
*n = sched_get_running_thread()->mother_proc->pid;
|
||||||
|
} else {
|
||||||
|
errno = EINVAL;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TIOCSPGRP:
|
||||||
|
// Accept but ignore: no foreground-pgrp tracking yet.
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
ret = -1;
|
ret = -1;
|
||||||
@@ -141,12 +270,14 @@ void console_init(void) {
|
|||||||
|
|
||||||
console_device->res.status |= POLLOUT;
|
console_device->res.status |= POLLOUT;
|
||||||
|
|
||||||
|
console_device->res.read = console_read;
|
||||||
console_device->res.write = console_write;
|
console_device->res.write = console_write;
|
||||||
console_device->res.ioctl = console_ioctl;
|
console_device->res.ioctl = console_ioctl;
|
||||||
|
|
||||||
console_device->decckm = false;
|
console_device->decckm = false;
|
||||||
|
|
||||||
devtmpfs_add_device((struct resource *)console_device, "console");
|
devtmpfs_add_device((struct resource *)console_device, "console");
|
||||||
|
devtmpfs_add_device((struct resource *)console_device, "tty");
|
||||||
|
|
||||||
kprintffos(false, "Bye bye!\n");
|
kprintffos(false, "Bye bye!\n");
|
||||||
framebuffer_clear(0x00eee8d5, 0);
|
framebuffer_clear(0x00eee8d5, 0);
|
||||||
|
|||||||
@@ -406,6 +406,9 @@ bool elf_load(struct pagemap *pagemap, struct resource *res, uint64_t load_base,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auxv->at_phdr = 0;
|
||||||
|
bool phdr_set = false;
|
||||||
|
|
||||||
for (size_t i = 0; i < header.e_phnum; i++) {
|
for (size_t i = 0; i < header.e_phnum; i++) {
|
||||||
Elf64_Phdr phdr;
|
Elf64_Phdr phdr;
|
||||||
if (res->read(res, NULL, &phdr, header.e_phoff + i * header.e_phentsize,
|
if (res->read(res, NULL, &phdr, header.e_phoff + i * header.e_phentsize,
|
||||||
@@ -446,10 +449,18 @@ bool elf_load(struct pagemap *pagemap, struct resource *res, uint64_t load_base,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fallback when no PT_PHDR: if this LOAD segment covers the
|
||||||
|
// program header table, derive at_phdr from it.
|
||||||
|
if (!phdr_set && header.e_phoff >= phdr.p_offset &&
|
||||||
|
header.e_phoff < phdr.p_offset + phdr.p_filesz) {
|
||||||
|
auxv->at_phdr = phdr.p_vaddr + (header.e_phoff - phdr.p_offset) + load_base;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PT_PHDR:
|
case PT_PHDR:
|
||||||
auxv->at_phdr = phdr.p_vaddr + load_base;
|
auxv->at_phdr = phdr.p_vaddr + load_base;
|
||||||
|
phdr_set = true;
|
||||||
break;
|
break;
|
||||||
case PT_INTERP: {
|
case PT_INTERP: {
|
||||||
void *path = kmalloc(phdr.p_filesz + 1);
|
void *path = kmalloc(phdr.p_filesz + 1);
|
||||||
|
|||||||
+2
-1
@@ -12,6 +12,7 @@
|
|||||||
#include "fs/elf.h"
|
#include "fs/elf.h"
|
||||||
#include "sched/sched_types.h"
|
#include "sched/sched_types.h"
|
||||||
#include "kargs.h"
|
#include "kargs.h"
|
||||||
|
#include "arch/x86_64/serial/serial.h"
|
||||||
|
|
||||||
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
|
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
|
||||||
# define printf_ printf
|
# define printf_ printf
|
||||||
@@ -650,7 +651,7 @@ bool print_now = false;
|
|||||||
void kputchar(char c) {
|
void kputchar(char c) {
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
kputchar('\r');
|
kputchar('\r');
|
||||||
//kputchar_(c);
|
kputchar_(c);
|
||||||
|
|
||||||
if (put_to_fb)
|
if (put_to_fb)
|
||||||
framebuffer_putchar(c);
|
framebuffer_putchar(c);
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ void debug_hex_dump(const void *data, size_t size);
|
|||||||
#define log_err(module, ...) logf(module, LVL_ERROR, __VA_ARGS__)
|
#define log_err(module, ...) logf(module, LVL_ERROR, __VA_ARGS__)
|
||||||
#define log_crit(module, ...) logf(module, LVL_CRITICAL, __VA_ARGS__)
|
#define log_crit(module, ...) logf(module, LVL_CRITICAL, __VA_ARGS__)
|
||||||
#define kprintf(...) kprintffos(put_to_fb, __VA_ARGS__)
|
#define kprintf(...) kprintffos(put_to_fb, __VA_ARGS__)
|
||||||
|
#define kputchar_ serial_putchar
|
||||||
|
|
||||||
|
|
||||||
#define putchar_ kputchar
|
#define putchar_ kputchar
|
||||||
|
|||||||
Reference in New Issue
Block a user