1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 2004-2009 H. Peter Anvin - All Rights Reserved
4  *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
5  *
6  *   Permission is hereby granted, free of charge, to any person
7  *   obtaining a copy of this software and associated documentation
8  *   files (the "Software"), to deal in the Software without
9  *   restriction, including without limitation the rights to use,
10  *   copy, modify, merge, publish, distribute, sublicense, and/or
11  *   sell copies of the Software, and to permit persons to whom
12  *   the Software is furnished to do so, subject to the following
13  *   conditions:
14  *
15  *   The above copyright notice and this permission notice shall
16  *   be included in all copies or substantial portions of the Software.
17  *
18  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  *   OTHER DEALINGS IN THE SOFTWARE.
26  *
27  * ----------------------------------------------------------------------- */
28 
29 /*
30  * vesacon_write.c
31  *
32  * Write to the screen using ANSI control codes (about as capable as
33  * DOS' ANSI.SYS.)
34  */
35 
36 #include <errno.h>
37 #include <string.h>
38 #include <com32.h>
39 #include <minmax.h>
40 #include <colortbl.h>
41 #include <console.h>
42 #include <klibc/compiler.h>
43 #include <syslinux/config.h>
44 #include "ansi.h"
45 #include "file.h"
46 #include "vesa/video.h"
47 
48 static void vesacon_erase(const struct term_state *, int, int, int, int);
49 static void vesacon_write_char(int, int, uint8_t, const struct term_state *);
50 static void vesacon_showcursor(const struct term_state *);
51 static void vesacon_setcursor(int x, int y, bool visible);
52 static void vesacon_scroll_up(const struct term_state *);
53 
54 static struct term_state ts;
55 static struct ansi_ops op = {
56     .erase = vesacon_erase,
57     .write_char = vesacon_write_char,
58     .showcursor = vesacon_showcursor,
59     .set_cursor = vesacon_setcursor,
60     .scroll_up = vesacon_scroll_up,
61     .beep = __ansicon_beep,
62 };
63 
64 static struct term_info ti = {
65     .disabled = 0,
66     .ts = &ts,
67     .op = &op
68 };
69 
70 /* Reference counter to the screen, to keep track of if we need
71    reinitialization. */
72 static int vesacon_counter = 0;
73 
74 static struct {
75     int x, y;
76 } vesacon_resolution = {
77     .x = DEFAULT_VESA_X_SIZE,
78     .y = DEFAULT_VESA_Y_SIZE,
79 };
80 
81 /* Set desired resolution - requires a full close/open cycle */
vesacon_set_resolution(int x,int y)82 void vesacon_set_resolution(int x, int y)
83 {
84     vesacon_resolution.x = x;
85     vesacon_resolution.y = y;
86 }
87 
88 /* Common setup */
__vesacon_open(struct file_info * fp)89 int __vesacon_open(struct file_info *fp)
90 {
91     (void)fp;
92 
93     if (!vesacon_counter) {
94 	/* Are we disabled? */
95 	if (syslinux_serial_console_info()->flowctl & 0x8000) {
96 	    ti.disabled = 1;
97 	    ti.rows = 25;
98 	    ti.cols = 80;
99 	} else {
100 	    /* Switch mode */
101 	    /* Deal with a resolution different from default build */
102 	    if (__vesacon_init(&vesacon_resolution.x, &vesacon_resolution.y)) {
103 		vesacon_counter = -1;
104 		return EAGAIN;
105 	    }
106 
107 	    /* Initial state */
108 	    __ansi_init(&ti);
109 	    ti.rows = __vesacon_text_rows;
110 	    ti.cols = __vesacon_text_cols;
111 	}
112     } else if (vesacon_counter == -1) {
113 	return EAGAIN;
114     }
115 
116     fp->o.rows = ti.rows;
117     fp->o.cols = ti.cols;
118 
119     vesacon_counter++;
120     return 0;
121 }
122 
__vesacon_close(struct file_info * fp)123 int __vesacon_close(struct file_info *fp)
124 {
125     (void)fp;
126 
127     vesacon_counter--;
128     return 0;
129 }
130 
131 /* Erase a region of the screen */
vesacon_erase(const struct term_state * st,int x0,int y0,int x1,int y1)132 static void vesacon_erase(const struct term_state *st,
133 			  int x0, int y0, int x1, int y1)
134 {
135     __vesacon_erase(x0, y0, x1, y1, st->cindex);
136 }
137 
138 /* Draw text on the screen */
vesacon_write_char(int x,int y,uint8_t ch,const struct term_state * st)139 static void vesacon_write_char(int x, int y, uint8_t ch,
140 			       const struct term_state *st)
141 {
142     __vesacon_write_char(x, y, ch, st->cindex);
143 }
144 
145 /* Show or hide the cursor */
146 static bool cursor_enabled = true;
vesacon_cursor_enable(bool enabled)147 void vesacon_cursor_enable(bool enabled)
148 {
149     cursor_enabled = enabled;
150 }
vesacon_showcursor(const struct term_state * st)151 static void vesacon_showcursor(const struct term_state *st)
152 {
153     vesacon_setcursor(st->xy.x, st->xy.y, st->cursor);
154 }
vesacon_setcursor(int x,int y,bool visible)155 static void vesacon_setcursor(int x, int y, bool visible)
156 {
157     __vesacon_set_cursor(x, y, visible && cursor_enabled);
158 }
159 
vesacon_scroll_up(const struct term_state * st)160 static void vesacon_scroll_up(const struct term_state *st)
161 {
162     __vesacon_scroll_up(1, st->cindex);
163 }
164 
__vesacon_write(struct file_info * fp,const void * buf,size_t count)165 ssize_t __vesacon_write(struct file_info *fp, const void *buf, size_t count)
166 {
167     const unsigned char *bufp = buf;
168     size_t n = 0;
169 
170     (void)fp;
171 
172     if (ti.disabled)
173 	return count;		/* Nothing to do */
174 
175     /* This only updates the shadow text buffer... */
176     while (count--) {
177 	__ansi_putchar(&ti, *bufp++);
178 	n++;
179     }
180 
181     /* This actually draws it */
182     __vesacon_doit();
183 
184     return n;
185 }
186 
187 const struct output_dev dev_vesacon_w = {
188     .dev_magic = __DEV_MAGIC,
189     .flags = __DEV_TTY | __DEV_OUTPUT,
190     .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND,
191     .write = __vesacon_write,
192     .close = __vesacon_close,
193     .open = __vesacon_open,
194     .fallback = &dev_ansicon_w,
195 };
196