]> git.proxmox.com Git - grub2.git/blob - term/i386/pc/vga_text.c
2008-11-22 Robert Millan <rmh@aybabtu.com>
[grub2.git] / term / i386 / pc / vga_text.c
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2007, 2008 Free Software Foundation, Inc.
4 *
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <grub/dl.h>
20 #include <grub/i386/vga_common.h>
21 #include <grub/i386/io.h>
22 #include <grub/types.h>
23
24 #define COLS 80
25 #define ROWS 25
26
27 static int grub_curr_x, grub_curr_y;
28
29 #define VGA_TEXT_SCREEN 0xb8000
30
31 #define CRTC_ADDR_PORT 0x3D4
32 #define CRTC_DATA_PORT 0x3D5
33
34 #define CRTC_CURSOR 0x0a
35 #define CRTC_CURSOR_ADDR_HIGH 0x0e
36 #define CRTC_CURSOR_ADDR_LOW 0x0f
37
38 #define CRTC_CURSOR_DISABLE (1 << 5)
39
40 static void
41 screen_write_char (int x, int y, short c)
42 {
43 ((short *) VGA_TEXT_SCREEN)[y * COLS + x] = c;
44 }
45
46 static short
47 screen_read_char (int x, int y)
48 {
49 return ((short *) VGA_TEXT_SCREEN)[y * COLS + x];
50 }
51
52 static void
53 update_cursor (void)
54 {
55 unsigned int pos = grub_curr_y * COLS + grub_curr_x;
56 grub_outb (CRTC_CURSOR_ADDR_HIGH, CRTC_ADDR_PORT);
57 grub_outb (pos >> 8, CRTC_DATA_PORT);
58 grub_outb (CRTC_CURSOR_ADDR_LOW, CRTC_ADDR_PORT);
59 grub_outb (pos & 0xFF, CRTC_DATA_PORT);
60 }
61
62 static void
63 inc_y (void)
64 {
65 grub_curr_x = 0;
66 if (grub_curr_y < ROWS - 1)
67 grub_curr_y++;
68 else
69 {
70 int x, y;
71 for (y = 0; y < ROWS; y++)
72 for (x = 0; x < COLS; x++)
73 screen_write_char (x, y, screen_read_char (x, y + 1));
74 }
75 }
76
77 static void
78 inc_x (void)
79 {
80 if (grub_curr_x >= COLS - 2)
81 inc_y ();
82 else
83 grub_curr_x++;
84 }
85
86 void
87 grub_console_real_putchar (int c)
88 {
89 switch (c)
90 {
91 case '\b':
92 if (grub_curr_x != 0)
93 screen_write_char (grub_curr_x--, grub_curr_y, ' ');
94 break;
95 case '\n':
96 inc_y ();
97 break;
98 case '\r':
99 grub_curr_x = 0;
100 break;
101 default:
102 screen_write_char (grub_curr_x,
103 grub_curr_y, c | (grub_console_cur_color << 8));
104 inc_x ();
105 }
106
107 update_cursor ();
108 }
109
110 static grub_uint16_t
111 grub_vga_text_getxy (void)
112 {
113 return (grub_curr_x << 8) | grub_curr_y;
114 }
115
116 static void
117 grub_vga_text_gotoxy (grub_uint8_t x, grub_uint8_t y)
118 {
119 grub_curr_x = x;
120 grub_curr_y = y;
121 update_cursor ();
122 }
123
124 static void
125 grub_vga_text_cls (void)
126 {
127 int i;
128 for (i = 0; i < ROWS * COLS; i++)
129 ((short *) VGA_TEXT_SCREEN)[i] = ' ' | (grub_console_cur_color << 8);
130 grub_vga_text_gotoxy (0, 0);
131 }
132
133 static void
134 grub_vga_text_setcursor (int on)
135 {
136 grub_uint8_t old;
137 grub_outb (CRTC_CURSOR, CRTC_ADDR_PORT);
138 old = grub_inb (CRTC_DATA_PORT);
139 if (on)
140 grub_outb (old & ~CRTC_CURSOR_DISABLE, CRTC_DATA_PORT);
141 else
142 grub_outb (old | CRTC_CURSOR_DISABLE, CRTC_DATA_PORT);
143 }
144
145 static grub_err_t
146 grub_vga_text_init_fini ()
147 {
148 grub_vga_text_cls ();
149 return 0;
150 }
151
152 static struct grub_term_output grub_vga_text_term =
153 {
154 .name = "vga_text",
155 .init = grub_vga_text_init_fini,
156 .fini = grub_vga_text_init_fini,
157 .putchar = grub_console_putchar,
158 .getcharwidth = grub_console_getcharwidth,
159 .getwh = grub_console_getwh,
160 .getxy = grub_vga_text_getxy,
161 .gotoxy = grub_vga_text_gotoxy,
162 .cls = grub_vga_text_cls,
163 .setcolorstate = grub_console_setcolorstate,
164 .setcolor = grub_console_setcolor,
165 .getcolor = grub_console_getcolor,
166 .setcursor = grub_vga_text_setcursor,
167 };
168
169 GRUB_MOD_INIT(vga_text)
170 {
171 grub_term_register_output (&grub_vga_text_term);
172 }
173
174 GRUB_MOD_FINI(vga_text)
175 {
176 grub_term_unregister_output (&grub_vga_text_term);
177 }