1/**
2 * \file
3 */
4
5/*
6 * Copyright (c) 2009, ETH Zurich.
7 * All rights reserved.
8 *
9 * This file is distributed under the terms in the attached LICENSE file.
10 * If you do not find this file, copies can be found by writing to:
11 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
12 */
13
14#include "vmkitmon.h"
15#include "console.h"
16#include <stdlib.h>
17#include <barrelfish/terminal.h>
18
19struct console *
20console_new (void)
21{
22    struct console *ret = calloc(1, sizeof(struct console));
23    return ret;
24}
25
26static int
27handle_set_cursor_position (struct console *c, struct guest *g)
28{
29    // only support mode 0 for now
30    if (guest_get_bh(g) != 0) {
31        return HANDLER_ERR_UNHANDELED;
32    }
33
34    c->cursor_pos_x = guest_get_dl(g);
35    c->cursor_pos_y = guest_get_dh(g);
36
37    return HANDLER_ERR_OK;
38}
39
40static int
41handle_write_char_with_attr (struct console *c, struct guest *g)
42{
43    // only support mode 0 for now
44    if (guest_get_bh(g) != 0) {
45        return HANDLER_ERR_UNHANDELED;
46    }
47    // we only support "normal" text output atm
48    if (guest_get_bl(g) != 7) {
49        return HANDLER_ERR_UNHANDELED;
50    }
51
52    // FIXME: Here we completely ignore the postition of the cursor atm since we
53    //        do not have proper terminal support in BF.
54    //        We also ignore multiple char writes, they make no sense atm.
55    int r;
56    char chr = guest_get_al(g);
57
58    r = terminal_write(&chr, 1);
59    assert(r == 1);
60
61    return HANDLER_ERR_OK;
62}
63
64static int
65handle_teletype_output (struct console *c, struct guest *g)
66{
67    // only support mode 0 for now
68    if (guest_get_bh(g) != 0) {
69        return HANDLER_ERR_UNHANDELED;
70    }
71
72    // we do not yet have a real understanding of the terminal, assume it is
73    // 80x25 and we simply insert new lines at the end of the "screen"
74    int r;
75    char chr = guest_get_al(g);
76
77    // treat CR and LF as column clearing chars
78    if (chr == '\r' || chr == '\n') {
79        c->cursor_pos_x = 0;
80    }
81    // insert a CR if we are passed the last column of the screen
82    else if (c->cursor_pos_x > 79) {
83        r = terminal_write("\n", 1);
84        assert(r == 1);
85        c->cursor_pos_x = 0;
86    }
87    // in all other cases just increase the column
88    else {
89        c->cursor_pos_x++;
90    }
91
92    r = terminal_write(&chr, 1);
93    assert(r == 1);
94
95    return HANDLER_ERR_OK;
96}
97
98static int
99handle_get_cursor_pos_and_size (struct console *c, struct guest *g)
100{
101    // only support mode 0 for now
102    if (guest_get_bh(g) != 0) {
103        return HANDLER_ERR_UNHANDELED;
104    }
105
106    // set ax to 0
107    guest_set_ax(g, 0);
108    // we do not support scan-lines
109    guest_set_cx(g, 0);
110
111    // set the position
112    guest_set_dl(g, c->cursor_pos_x);
113    guest_set_dh(g, c->cursor_pos_y);
114
115    return HANDLER_ERR_OK;
116}
117
118static int
119handle_set_text_cursor_shape (struct console *c, struct guest *g)
120{
121    // we only handle primitive cursors
122    if (guest_get_cx(g) != 0) {
123        printf("console: Unsupported cursor requested\n");
124        return HANDLER_ERR_FATAL;
125    }
126
127    return HANDLER_ERR_OK;
128}
129
130static int
131handle_get_current_video_mode (struct console *c, struct guest *g)
132{
133    // FIXME: for the terminal to be more flexible this should not be hardcoded
134    guest_set_ah(g, 80),
135    guest_set_al(g, 0x6); // VGA, 80x25, 8x8 box, res 640x200, 2 colors
136    guest_set_bh(g, 0);
137
138    return HANDLER_ERR_OK;
139}
140
141static int
142handle_get_ega_info (struct console *c, struct guest *g)
143{
144    // FIXME: only partially implemented, linux wants BX to be 0x10 to believe
145    //        it is confronted with a CGA card.
146    guest_set_bx(g, 0x10);
147
148    return HANDLER_ERR_OK;
149}
150
151static int
152handle_get_svga_info (struct console *c, struct guest *g)
153{
154    // we do not support vesa yet
155    guest_set_ax(g, 0);
156
157    return HANDLER_ERR_OK;
158}
159
160static int
161handle_set_video_mode (struct console *c, struct guest *g)
162{
163    // FIXME: Ignored for now.
164
165    return HANDLER_ERR_OK;
166}
167
168int
169console_handle_int10 (struct console *c, struct guest *g)
170{
171    // VESA SuperVGA BIOS (VBE) - GET SuperVGA INFORMATION
172    if (guest_get_ax(g) == 0x4f00) {
173        return handle_get_svga_info(c, g);
174    }
175    // VIDEO - SET VIDEO MODE
176    if (guest_get_ah(g) == 0x0) {
177        return handle_set_video_mode(c, g);
178    }
179    // VIDEO - SET TEXT-MODE CURSOR SHAPE
180    if (guest_get_ah(g) == 0x1) {
181        return handle_set_text_cursor_shape(c, g);
182    }
183    // VIDEO - SET CURSOR POSITION
184    else if (guest_get_ah(g) == 0x2) {
185        return handle_set_cursor_position(c, g);
186    }
187    // VIDEO - GET CURSOR POSITION AND SIZE
188    else if (guest_get_ah(g) == 0x3) {
189        return handle_get_cursor_pos_and_size(c, g);
190    }
191    // VIDEO - WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION
192    else if (guest_get_ah(g) == 0x9) {
193        return handle_write_char_with_attr(c, g);
194    }
195    // VIDEO - TELETYPE OUTPUT
196    else if (guest_get_ah(g) == 0xe) {
197        return handle_teletype_output(c, g);
198    }
199    // VIDEO - GET CURRENT VIDEO MODEL_CGA
200    else if (guest_get_ah(g) == 0xf) {
201        return handle_get_current_video_mode(c, g);
202    }
203    // VIDEO - ALTERNATE FUNCTION SELECT (PS, EGA, VGA, MCGA) - GET EGA INFO
204    else if (guest_get_ah(g) == 0x12 && guest_get_bl(g) == 0x10) {
205        return handle_get_ega_info(c, g);
206    }
207
208    return HANDLER_ERR_UNHANDELED;
209}
210