Compare commits
2 Commits
b28a6bcf29
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
19521c6ab4
|
|||
|
e9e750bd74
|
@@ -7,3 +7,4 @@ void serial_putchar(char ch);
|
||||
void serial_puts(char *str);
|
||||
char serial_get_byte(void);
|
||||
char serial_getchar(void);
|
||||
int serial_received(void);
|
||||
+132
-1
@@ -9,6 +9,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "arch/x86_64/serial/serial.h"
|
||||
#include "sched/sched.h"
|
||||
|
||||
struct console {
|
||||
struct resource res;
|
||||
@@ -19,6 +21,11 @@ struct console {
|
||||
|
||||
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,
|
||||
struct f_description *description, const void *buf,
|
||||
off_t offset, size_t count) {
|
||||
@@ -34,13 +41,114 @@ static ssize_t console_write(struct resource *this,
|
||||
|
||||
char *r = (char *)buf;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
framebuffer_putchar(r[i]);
|
||||
console_emit(r[i]);
|
||||
}
|
||||
|
||||
spinlock_drop(&this->lock);
|
||||
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,
|
||||
uint64_t request, uint64_t arg) {
|
||||
(void)description;
|
||||
@@ -76,6 +184,27 @@ int console_ioctl(struct resource *this, struct f_description *description,
|
||||
}
|
||||
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:
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
@@ -141,12 +270,14 @@ void console_init(void) {
|
||||
|
||||
console_device->res.status |= POLLOUT;
|
||||
|
||||
console_device->res.read = console_read;
|
||||
console_device->res.write = console_write;
|
||||
console_device->res.ioctl = console_ioctl;
|
||||
|
||||
console_device->decckm = false;
|
||||
|
||||
devtmpfs_add_device((struct resource *)console_device, "console");
|
||||
devtmpfs_add_device((struct resource *)console_device, "tty");
|
||||
|
||||
kprintffos(false, "Bye bye!\n");
|
||||
framebuffer_clear(0x00eee8d5, 0);
|
||||
|
||||
+13
-4
@@ -149,9 +149,7 @@ uint64_t module_load(const char *path) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
|
||||
ehdr->e_ident[EI_DATA] != ELFDATA2LSB || ehdr->e_ident[EI_OSABI] != 0 ||
|
||||
ehdr->e_machine != EM_X86_64) {
|
||||
if (ehdr->e_ident[EI_CLASS] != ELFCLASS64 || ehdr->e_ident[EI_DATA] != ELFDATA2LSB || (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE && ehdr->e_ident[EI_OSABI] != ELFOSABI_LINUX) || ehdr->e_machine != EM_X86_64) {
|
||||
kprintf("This ELF isn't for us\n");
|
||||
return 1;
|
||||
}
|
||||
@@ -404,10 +402,13 @@ bool elf_load(struct pagemap *pagemap, struct resource *res, uint64_t load_base,
|
||||
|
||||
if (header.e_ident[EI_CLASS] != ELFCLASS64 ||
|
||||
header.e_ident[EI_DATA] != ELFDATA2LSB ||
|
||||
header.e_ident[EI_OSABI] != 0 || header.e_machine != EM_X86_64) {
|
||||
(header.e_ident[EI_OSABI] != ELFOSABI_NONE && header.e_ident[EI_OSABI] != ELFOSABI_LINUX) || header.e_machine != EM_X86_64) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auxv->at_phdr = 0;
|
||||
bool phdr_set = false;
|
||||
|
||||
for (size_t i = 0; i < header.e_phnum; i++) {
|
||||
Elf64_Phdr phdr;
|
||||
if (res->read(res, NULL, &phdr, header.e_phoff + i * header.e_phentsize,
|
||||
@@ -448,10 +449,18 @@ bool elf_load(struct pagemap *pagemap, struct resource *res, uint64_t load_base,
|
||||
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;
|
||||
}
|
||||
case PT_PHDR:
|
||||
auxv->at_phdr = phdr.p_vaddr + load_base;
|
||||
phdr_set = true;
|
||||
break;
|
||||
case PT_INTERP: {
|
||||
void *path = kmalloc(phdr.p_filesz + 1);
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@
|
||||
#include "fs/elf.h"
|
||||
#include "sched/sched_types.h"
|
||||
#include "kargs.h"
|
||||
#include "arch/x86_64/serial/serial.h"
|
||||
|
||||
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
|
||||
# define printf_ printf
|
||||
@@ -650,7 +651,7 @@ bool print_now = false;
|
||||
void kputchar(char c) {
|
||||
if (c == '\n')
|
||||
kputchar('\r');
|
||||
//kputchar_(c);
|
||||
kputchar_(c);
|
||||
|
||||
if (put_to_fb)
|
||||
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_crit(module, ...) logf(module, LVL_CRITICAL, __VA_ARGS__)
|
||||
#define kprintf(...) kprintffos(put_to_fb, __VA_ARGS__)
|
||||
#define kputchar_ serial_putchar
|
||||
|
||||
|
||||
#define putchar_ kputchar
|
||||
|
||||
Reference in New Issue
Block a user