Significant terminal updates. Scrolling is faster, ansi support (limited), and some other things

This commit is contained in:
Kevin Lange 2011-04-04 18:51:55 -05:00
parent 9dea4713c8
commit 5404428b4a
12 changed files with 388 additions and 38 deletions

View File

@ -9,7 +9,7 @@ __asm__(".code16gcc\n");
#define PRINT(s) __asm__ ("movw %0, %%si\ncall _print" : : "l"((short)(int)s))
void read(unsigned char count, unsigned char sector, short segment, short offset)
void read(unsigned short count, unsigned short sector, unsigned short segment, unsigned short offset)
{
__asm__ __volatile__ (
"movw %0, %%es\n"
@ -33,9 +33,12 @@ void read(unsigned char count, unsigned char sector, short segment, short offset
void main()
{
PRINT("Loading... ");
read(6,2,0,0x7e00);
read(0x18, 0x68, 0x1000, 0x0);
read(0x14c, 0x82, 0x1000, 0x3000);
PRINT("Ready.\r\n");
/* Let's do this... */
__asm__ __volatile__ ("jmp $0x00, $0x7e00");
__asm__ __volatile__ ("jmpl $0x1, $0x0");
PRINT("I definitely went somewhere...\r\n");
}

0
initrd/dev/.dummy Normal file
View File

View File

@ -2,6 +2,23 @@
#define from_bcd(val) ((val / 16) * 10 + (val & 0xf))
void
get_date(
uint16_t * month,
uint16_t * day
) {
uint16_t values[128];
uint16_t index;
__asm__ __volatile__ ("cli");
for (index = 0; index < 128; ++index) {
outportb(0x70, index);
values[index] = inportb(0x71);
}
__asm__ __volatile__ ("sti");
*month = from_bcd(values[8]);
*day = from_bcd(values[7]);
}
void
get_time(
uint16_t * hours,

38
kernel/core/fs/devfs.c Normal file
View File

@ -0,0 +1,38 @@
/*
* ToAruOS DevFS
*
* vim:noexpandtab
* vim:tabstop=4
*/
#include <system.h>
#include <fs.h>
uint32_t read_devfs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
uint32_t write_devfs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
void open_devfs(fs_node_t *node, uint8_t read, uint8_t write);
void close_devfs(fs_node_t *node);
struct dirent *readdir_devfs(fs_node_t *node, uint32_t index);
fs_node_t *finddir_devfs(fs_node_t *node, char *name);
fs_node_t * devfs_root;
/*
* Install the DevFS to the given path.
* Path should be `/dev`
*/
void
devfs_install(char * path) {
fs_node_t * dev_node = kopen(path,0);
}
/*
* These functions require that the requested node have a valid handler of their own
* and are not part of the devfs natively
*/
uint32_t read_devfs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
return -1;
}
uint32_t write_devfs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
return -1;
}

View File

@ -202,3 +202,17 @@ putch(
}
}
/*
* Externally Set Keyboard States
*/
void
set_kbd(
int shift,
int alt,
int ctrl
) {
keyboard_state.shift = shift;
keyboard_state.alt = alt;
keyboard_state.ctrl = ctrl;
}

View File

@ -106,7 +106,11 @@ kprintf(
}
buf[ptr] = '\0';
va_end(args);
puts(buf);
if (ansi_ready) {
ansi_print(buf);
} else {
puts(buf);
}
}
char * kgets_buffer = NULL;

View File

@ -66,3 +66,10 @@ serial_send(char out) {
while (serial_transmit_empty() == 0);
outportb(SERIAL_PORT_A, out);
}
void
serial_string(char * out) {
for (int i = 0; i < strlen(out); ++i) {
serial_send(out[i]);
}
}

View File

@ -27,12 +27,19 @@ start_shell() {
char path[1024] = {'/', '\0'};
/* File system node for the working directory */
fs_node_t * node = fs_root;
char * username = "klange";
char * hostname = "piko";
ansi_init();
while (1) {
/* Read buffer */
char buffer[1024];
int size;
/* Print the prompt */
kprintf("smash %s $ ", path);
uint16_t month, day, hours, minutes, seconds;
get_date(&month, &day);
get_time(&hours, &minutes, &seconds);
kprintf("\033[1m[\033[1;33m%s \033[1;32m%s \033[1;31m%d/%d \033[1;34m%d:%d:%d\033[0m \033[0m%s\033[1m]\033[0m\n\033[1;32m$\033[0m ",
username, hostname, month, day, hours, minutes, seconds, path);
/* Read commands */
size = kgets((char *)&buffer, 1023);
if (size < 1) {
@ -120,7 +127,7 @@ start_shell() {
size_t bytes_read = read_fs(file, 0, file->length, (uint8_t *)bufferb);
size_t i = 0;
for (i = 0; i < bytes_read; ++i) {
writech(bufferb[i]);
ansi_put(bufferb[i]);
}
free(bufferb);
close_fs(file);
@ -198,24 +205,10 @@ start_shell() {
} else if (!strcmp(cmd, "exit")) {
kprintf("Good byte.\n");
break;
} else if (!strcmp(cmd, "short-text")) {
kprintf("I'm going to make text shorter. This is a silly demo.\n");
outportb(0x3D4, 0x9);
outportb(0x3D5, 0x0E);
} else if (!strcmp(cmd, "cpu-detect")) {
detect_cpu();
} else if (!strcmp(cmd, "scroll")) {
bochs_scroll();
} else if (!strcmp(cmd, "vid-mode")) {
if (tokenid < 2) {
kprintf("Please select a graphics driver: bochs\n");
} else {
if (!strcmp(argv[1], "bochs")) {
graphics_install_bochs();
} else {
kprintf("Unknown graphics driver: %s\n", argv[1]);
}
}
} else if (!strcmp(cmd, "logo")) {
if (tokenid < 2) {
bochs_draw_logo("/bs.bmp");
@ -240,6 +233,14 @@ start_shell() {
int y1 = krand() % 768;
bochs_draw_line(x0,x1,y0,y1, krand() % 0xFFFFFF);
}
} else if (!strcmp(cmd, "test-scroll")) {
bochs_set_y_offset(12 * 20);
} else if (!strcmp(cmd, "reset-keyboard")) {
/* Reset the shift/alt/ctrl statuses, in case they get messed up */
set_kbd(0,0,0);
} else if (!strcmp(cmd, "test-ansi")) {
ansi_print("This is a \033[32mtest\033[0m of the \033[33mANSI\033[0m driver.\n");
ansi_print("This is a \033[32;1mte\033[34mst\033[0m of \033[1mthe \033[33mANSI\033[0m driver.\n");
} else {
kprintf("Unrecognized command: %s\n", cmd);
}

233
kernel/core/video/ansi.c Normal file
View File

@ -0,0 +1,233 @@
/*
* ANSI-esque Terminal Escape Driver
* vim:tabstop=4
* vim:noexpandtab
*/
#include <system.h>
/* Triggers escape mode. */
#define ANSI_ESCAPE 27
/* Escape verify */
#define ANSI_BRACKET '['
/* Anything in this range (should) exit escape mode. */
#define ANSI_LOW 'A'
#define ANSI_HIGH 'u'
/* Escape commands */
#define ANSI_CUU 'A' /* CUrsor Up */
#define ANSI_CUD 'B' /* CUrsor Down */
#define ANSI_CUF 'C' /* CUrsor Forward */
#define ANSI_CUB 'D' /* CUrsor Back */
#define ANSI_CNL 'E' /* Cursor Next Line */
#define ANSI_CPL 'F' /* Cursor Previous Line */
#define ANSI_CHA 'G' /* Cursor Horizontal Absolute */
#define ANSI_CUP 'H' /* CUrsor Position */
#define ANSI_ED 'J' /* Erase Data */
#define ANSI_EL 'K' /* Erase in Line */
#define ANSI_SU 'S' /* Scroll Up */
#define ANSI_SD 'T' /* Scroll Down */
#define ANSI_HVP 'f' /* Horizontal & Vertical Pos. XXX: SAME AS CUP */
#define ANSI_SGR 'm' /* Select Graphic Rendition */
#define ANSI_DSR 'n' /* Device Status Report XXX: Push to kgets() buffer? */
#define ANSI_SCP 's' /* Save Cursor Position */
#define ANSI_RCP 'u' /* Restore Cursor Position */
#define ANSI_HIDE 'l' /* DECTCEM - Hide Cursor */
#define ANSI_SHOW 'h' /* DECTCEM - Show Cursor */
/* Display flags */
#define ANSI_BOLD 0x01
#define ANSI_UNDERLINE 0x02
#define ANSI_ITALIC 0x04
#define ANSI_FRAKTUR 0x08 /* As if I'll ever implement that */
#define ANSI_DOUBLEU 0x10
#define ANSI_OVERLINE 0x20
#define ANSI_BLINK 0x40
#define ANSI_CROSS 0x80 /* And that's all I'm going to support */
/* State machine status */
static struct _ansi_state {
uint16_t x ; /* Current cursor location */
uint16_t y ; /* " " " */
uint16_t save_x;
uint16_t save_y;
uint32_t width ;
uint32_t height;
uint8_t fg ; /* Current foreground color */
uint8_t bg ; /* Current background color */
uint8_t flags ; /* Bright, etc. */
uint8_t escape; /* Escape status */
uint8_t buflen; /* Buffer Length */
char * buffer; /* Previous buffer */
} state;
void (*ansi_writer)(char) = &bochs_write;
void
ansi_dump_buffer() {
/* Assuming bochs_write() is the unprocessed output function */
for (int i = 0; i < state.buflen; ++i) {
ansi_writer(state.buffer[i]);
}
}
void
ansi_buf_add(
char c
) {
state.buffer[state.buflen] = c;
state.buflen++;
state.buffer[state.buflen] = '\0';
}
void
ansi_put(
char c
) {
switch (state.escape) {
case 0:
/* We are not escaped, check for escape character */
if (c == ANSI_ESCAPE) {
/*
* Enable escape mode, setup a buffer,
* fill the buffer, get out of here.
*/
state.escape = 1;
state.buffer = malloc(sizeof(char) * 100);
state.buflen = 0;
ansi_buf_add(c);
return;
} else {
ansi_writer(c);
}
break;
case 1:
/* We're ready for [ */
if (c == ANSI_BRACKET) {
state.escape = 2;
ansi_buf_add(c);
} else {
/* This isn't a bracket, we're not actually escaped!
* Get out of here! */
ansi_dump_buffer();
ansi_writer(c);
state.escape = 0;
free(state.buffer);
state.buffer = NULL;
state.buflen = 0;
return;
}
break;
case 2:
if (c >= ANSI_LOW && c <= ANSI_HIGH) {
/* Woah, woah, let's see here. */
char * pch; /* tokenizer pointer */
char * save; /* strtok_r pointer */
char * argv[1024]; /* escape arguments */
/* Get rid of the front of the buffer */
strtok_r(state.buffer,"[",&save);
pch = strtok_r(NULL,";",&save);
/* argc = Number of arguments, obviously */
int argc = 0;
while (pch != NULL) {
argv[argc] = (char *)pch;
++argc;
pch = strtok_r(NULL,";",&save);
}
argv[argc] = NULL;
/* Alright, let's do this */
switch (c) {
case ANSI_SGR:
/* Set Graphics Rendition */
if (argc == 0) {
/* Default = 0 */
argv[0] = "0";
argc = 1;
}
for (int i = 0; i < argc; ++i) {
int arg = atoi(argv[i]);
if (arg >= 100 && arg < 110) {
/* Bright background */
state.bg = 8 + (arg - 100);
} else if (arg >= 90 && arg < 100) {
/* Bright foreground */
state.fg = 8 + (arg - 90);
} else if (arg >= 40 && arg < 50) {
/* Set background */
state.bg = arg - 40;
} else if (arg >= 30 && arg < 40) {
/* Set Foreground */
state.fg = arg - 30;
} else if (arg == 20) {
/* FRAKTUR: Like old German stuff */
state.flags |= ANSI_FRAKTUR;
} else if (arg == 9) {
/* X-OUT */
state.flags |= ANSI_CROSS;
} else if (arg == 7) {
/* INVERT: Swap foreground / background */
uint8_t temp = state.fg;
state.fg = state.bg;
state.bg = temp;
} else if (arg == 5) {
/* BLINK: I have no idea how I'm going to make this work! */
state.flags |= ANSI_BLINK;
} else if (arg == 4) {
/* UNDERLINE */
state.flags |= ANSI_UNDERLINE;
} else if (arg == 3) {
/* ITALIC: Oblique */
state.flags |= ANSI_ITALIC;
} else if (arg == 1) {
/* BOLD/BRIGHT: Brighten the output color */
state.flags |= ANSI_BOLD;
} else if (arg == 0) {
/* Reset everything */
state.fg = 7;
state.bg = 0;
state.flags = 0;
}
}
break;
default:
/* Meh */
break;
}
/* Set the states */
if (state.flags & ANSI_BOLD) {
bochs_set_colors(state.fg % 8 + 8, state.bg);
} else {
bochs_set_colors(state.fg, state.bg);
}
/* Clear out the buffer */
free(state.buffer);
state.buffer = NULL;
state.buflen = 0;
state.escape = 0;
return;
} else {
/* Still escaped */
ansi_buf_add(c);
}
break;
}
}
void
ansi_init() {
/* Terminal Defaults */
state.fg = 7; /* Light grey */
state.bg = 0; /* Black */
state.flags = 0; /* Nothing fancy*/
state.width = 128; /* 1024 / 8 */
state.height = 64; /* 768 / 12 */
ansi_ready = 1;
}
void
ansi_print(char * c) {
uint32_t len = strlen(c);
for (uint32_t i = 0; i < len; ++i) {
ansi_put(c[i]);
/* Assume our serial output is also kinda smart */
serial_send(c[i]);
}
}

View File

@ -10,6 +10,7 @@
#define PREFERRED_X 1024
#define PREFERRED_Y 768
#define PREFERRED_VY 4096
#define PREFERRED_B 32
uint16_t bochs_resolution_x = 0;
@ -26,6 +27,19 @@ static short csr_y = 0;
static uint8_t * term_buffer;
static uint8_t current_fg = 7;
static uint8_t current_bg = 0;
static uint16_t current_scroll = 0;
void
bochs_set_y_offset(uint16_t y) {
outports(0x1CE, 0x9);
outports(0x1CF, y);
current_scroll = y;
}
uint16_t
bochs_current_scroll() {
return current_scroll;
}
void
graphics_install_bochs() {
@ -53,6 +67,9 @@ graphics_install_bochs() {
/* Set bpp to 32 */
outports(0x1CE, 0x03);
outports(0x1CF, PREFERRED_B);
/* Set Virtual Height to stuff */
outports(0x1CE, 0x07);
outports(0x1CF, PREFERRED_VY);
/* Re-enable VBE */
outports(0x1CE, 0x04);
outports(0x1CF, 0x41);
@ -100,7 +117,7 @@ bochs_set_point(
uint16_t y,
uint32_t color
) {
BOCHS_VID_MEMORY[(y * bochs_resolution_x + x)] = color;
BOCHS_VID_MEMORY[((y + current_scroll) * bochs_resolution_x + x)] = color;
}
void
@ -200,11 +217,12 @@ uint32_t bochs_colors[16] = {
/* white */ 0xFFFFFF
};
static void cell_set(uint16_t x, uint16_t y, uint8_t c, uint8_t fg, uint8_t bg) {
static void cell_set(uint16_t x, uint16_t y, uint8_t c, uint8_t fg, uint8_t bg, uint8_t flags) {
uint8_t * cell = (uint8_t *)((uintptr_t)term_buffer + (y * TERM_WIDTH + x) * 4);
cell[0] = c;
cell[1] = fg;
cell[2] = bg;
cell[3] = flags;
}
static uint16_t cell_ch(uint16_t x, uint16_t y) {
@ -238,30 +256,34 @@ void bochs_redraw() {
void bochs_term_scroll() {
/* Oh dear */
bochs_scroll();
if (current_scroll + 24 >= 3328) {
/* And here's where it gets hacky */
__asm__ __volatile__ ("cli");
uint32_t size = sizeof(uint32_t) * bochs_resolution_x * (bochs_resolution_y - 12);
memmove((void *)BOCHS_VID_MEMORY, (void *)((uintptr_t)BOCHS_VID_MEMORY + bochs_resolution_x * (current_scroll + 12) * sizeof(uint32_t)), size);
__asm__ __volatile__ ("sti");
bochs_set_y_offset(0);
} else {
bochs_set_y_offset(current_scroll + 12);
}
for (uint16_t y = 0; y < TERM_HEIGHT - 1; ++y) {
for (uint16_t x = 0; x < TERM_WIDTH; ++x) {
cell_set(x,y,cell_ch(x,y+1),cell_fg(x,y+1),cell_bg(x,y+1));
cell_set(x,y,cell_ch(x,y+1),cell_fg(x,y+1),cell_bg(x,y+1), 0);
}
}
for (uint16_t x = 0; x < TERM_WIDTH; ++x) {
cell_set(x, TERM_HEIGHT-1,' ',current_fg, current_bg);
cell_set(x, TERM_HEIGHT-1,' ',current_fg, current_bg,0);
cell_redraw(x, TERM_HEIGHT-1);
}
//bochs_redraw();
}
void bochs_term_clear() {
/* Oh dear */
csr_x = 0;
csr_y = 0;
for (uint16_t y = 0; y < TERM_HEIGHT; ++y) {
for (uint16_t x = 0; x < TERM_WIDTH; ++x) {
cell_set(x,y,' ',current_fg, current_bg);
}
}
bochs_redraw();
memset((void *)term_buffer, 0x00,TERM_WIDTH * TERM_HEIGHT * sizeof(uint8_t) * 4);
memset((void *)BOCHS_VID_MEMORY, 0x00, sizeof(uint32_t) * bochs_resolution_x * bochs_resolution_y);
bochs_set_y_offset(0);
}
void bochs_set_colors(uint8_t fg, uint8_t bg) {
@ -286,17 +308,17 @@ void bochs_write(char c) {
if (c == '\n') {
for (uint16_t i = csr_x; i < TERM_WIDTH; ++i) {
/* I like this behaviour */
cell_set(i, csr_y, ' ',current_fg, current_bg);
cell_set(i, csr_y, ' ',current_fg, current_bg, 0);
cell_redraw(i, csr_y);
}
csr_x = 0;
++csr_y;
} else if (c == '\b') {
--csr_x;
cell_set(csr_x, csr_y, ' ',current_fg, current_bg);
cell_set(csr_x, csr_y, ' ',current_fg, current_bg, 0);
cell_redraw(csr_x, csr_y);
} else {
cell_set(csr_x,csr_y, c, current_fg, current_bg);
cell_set(csr_x,csr_y, c, current_fg, current_bg, 0);
cell_redraw(csr_x,csr_y);
csr_x++;
}

View File

@ -103,6 +103,7 @@ keyboard_buffer_t keyboard_buffer_handler;
extern void keyboard_install();
extern void keyboard_wait();
extern void putch(unsigned char c);
extern void set_kbd(int,int,int);
/* kprintf */
extern void kprintf(const char *fmt, ...);
@ -164,6 +165,7 @@ extern void start_shell();
extern void serial_install();
extern char serial_recv();
extern void serial_send(char out);
extern void serial_string(char * out);
/* Tasks */
extern uintptr_t read_eip();
@ -227,6 +229,7 @@ extern void parse_args(char * argv);
/* CMOS */
extern void get_time(uint16_t * hours, uint16_t * minutes, uint16_t * seconds);
extern void get_date(uint16_t * month, uint16_t * day);
/* CPU Detect by Brynet */
extern int detect_cpu();
@ -244,6 +247,8 @@ extern uint16_t bochs_resolution_x;
extern uint16_t bochs_resolution_y;
extern uint16_t bochs_resolution_b;
extern uint32_t bochs_colors[];
extern void bochs_set_y_offset(uint16_t y);
extern uint16_t bochs_current_scroll();
/* Terminal functions */
extern void bochs_term_clear();
extern void bochs_write(char c);
@ -251,6 +256,12 @@ extern void bochs_reset_colors();
extern void bochs_set_colors(uint8_t, uint8_t);
extern void bochs_draw_line(uint16_t,uint16_t,uint16_t,uint16_t,uint32_t);
/* ANSI Terminal Escape Processor */
void ansi_put(char c);
void ansi_print(char * c);
void ansi_init();
int ansi_ready;
extern uint8_t number_font[][12];
/* Floating Point Unit */

View File

@ -156,7 +156,7 @@ int main(int argc, char ** argv) {
fprintf(stderr,"Failed to locate the requested file on the disk image.\n");
return -1;
}
uint32_t offset = 0x8000; /* Destination offset */
uint32_t offset = 0x10000; /* Destination offset */
uint32_t _block = 0;
uint32_t _block_last = 0;
for (uint32_t i = 0; i < fnode->blocks; ++i) {
@ -165,7 +165,7 @@ int main(int argc, char ** argv) {
if (_block != 0) {
uint32_t size = (_block_last - _block + 1) * (0x400 << sblock->log_block_size);
uint32_t place = ext2_get_block_offset(_block);
fprintf(stdout, "0x%x, 0x%x -> 0x%x\n", place, size, offset);
fprintf(stdout, "read(0x%x, 0x%x, 0x%x, 0x%x);\n", size / 512, place / 512, 0x1000, offset % 0x10000);
offset += size;
}
if (block == 0) { break; }