IBNOS
console.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Michael Müller
3  * Copyright (c) 2014, Sebastian Lackner
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #include <console/console.h>
29 #include <memory/physmem.h>
30 #include <util/util.h>
31 #include <io/io.h>
32 
33 #define VGA_WIDTH 80
34 #define VGA_HEIGHT 25
35 #define CHAR_OFFSET(x, y) ((y) * VGA_WIDTH + (x))
36 
38 static uint16_t *videoTextMemory = (uint16_t *)0xB8000;
39 static uint8_t *videoFontMemory = (uint8_t *)0xA0000;
41 static UNUSED uint16_t *videoIOPort = (uint16_t *)0x0463;
42 
44 static uint8_t cursorX = 0;
45 static uint8_t cursorY = 0;
46 
48 static uint8_t consoleColor = MAKE_COLOR(COLOR_WHITE, COLOR_BLACK);
49 
51 static uint32_t consoleFlags = CONFLAGS_ECHO | CONFLAGS_HWCURSOR | CONFLAGS_HWCURSOR_AUTO;
52 
54 static uint8_t cursorHardwareX = 0;
55 static uint8_t cursorHardwareY = 0;
56 
58 static const char hexTable[] = "0123456789ABCDEF";
59 
61 static void __consoleSetMiscOutputRegister(bool set)
62 {
63  uint8_t value = inb(0x3CC);
64 
65  if (set)
66  value |= 1;
67  else
68  value &= ~1;
69 
70  outb(0x3C2, value);
71 }
72 
80 {
81  /* Protect the whole VGA address space */
82  physMemProtectBootEntry(0xA0000, 0xC0000 - 0xA0000);
83 }
84 
91 {
92  uint32_t x, y;
93  for (y = 0; y < VGA_HEIGHT; y++)
94  {
95  for (x = 0; x < VGA_WIDTH; x++)
96  videoTextMemory[CHAR_OFFSET(x, y)] = ' ' | (consoleColor << 8);
97  }
98 
99  consoleSetCursorPos(0, 0);
100 
101  if (consoleFlags & CONFLAGS_HWCURSOR_AUTO)
103 }
104 
113 void consoleSetColor(uint8_t color)
114 {
115  consoleColor = color;
116 }
117 
125 {
126  return consoleColor;
127 }
128 
129 
135 {
136  return consoleColor & 15;
137 }
138 
144 {
145  return (consoleColor >> 4) & 15;
146 }
147 
156 void consolePutChar(char chr)
157 {
158  bool rawMode = consoleFlags & CONFLAGS_RAW_MODE;
159  if (rawMode || chr != '\n')
160  {
161  videoTextMemory[CHAR_OFFSET(cursorX, cursorY)] = (chr & 0xFF) | (consoleColor << 8);
162  cursorX++;
163  }
164 
165  if ((chr == '\n' && !rawMode) || cursorX >= VGA_WIDTH)
166  {
167  cursorY++;
168  cursorX = 0;
169  }
170 
171  if (cursorY >= VGA_HEIGHT)
172  {
173  if (rawMode)
174  cursorY = 0;
175  else
176  {
177  consoleScrollUp();
178  cursorY = VGA_HEIGHT - 1;
179  }
180  }
181 
182  if (consoleFlags & CONFLAGS_HWCURSOR_AUTO)
183  consoleSetHardwareCursor(cursorX, cursorY);
184 }
185 
193 void consoleEchoChar(char chr)
194 {
195  if (consoleFlags & CONFLAGS_ECHO)
196  consolePutChar(chr);
197 }
198 
208 void consolePutCharRaw(uint16_t chr)
209 {
210  bool rawMode = consoleFlags & CONFLAGS_RAW_MODE;
211  videoTextMemory[CHAR_OFFSET(cursorX, cursorY)] = chr;
212  cursorX++;
213 
214  if ((RAW_CHAR_CHR(chr) == '\n' && !rawMode) || cursorX >= VGA_WIDTH)
215  {
216  cursorY++;
217  cursorX = 0;
218  }
219 
220  if (cursorY >= VGA_HEIGHT)
221  {
222  if (rawMode)
223  cursorY = 0;
224  else
225  {
226  consoleScrollUp();
227  cursorY = VGA_HEIGHT - 1;
228  }
229  }
230 
231  if (consoleFlags & CONFLAGS_HWCURSOR_AUTO)
232  consoleSetHardwareCursor(cursorX, cursorY);
233 }
234 
240 void consoleWriteString(const char *str)
241 {
242  while (*str)
243  {
244  consolePutChar(*str++);
245  }
246 }
247 
254 void consoleWriteStringLen(const char *str, size_t len)
255 {
256  while (len)
257  {
258  consolePutChar(*str++);
259  len--;
260  }
261 }
262 
269 void consoleWriteRawLen(const uint16_t *data, size_t count)
270 {
271  while (count)
272  {
273  consolePutCharRaw(*data++);
274  count--;
275  }
276 }
277 
287 void consoleWriteStringMax(const char *str, size_t len)
288 {
289  while (len && *str)
290  {
291  consolePutChar(*str++);
292  len--;
293  }
294 }
295 
303 void consoleWriteHex32(uint32_t value)
304 {
305  char buf[8];
306  int i;
307 
308  for (i = 7; i >= 0; i--)
309  {
310  buf[i] = hexTable[value & 0xF];
311  value >>= 4;
312  }
313 
314  consoleWriteString("0x");
315  consoleWriteStringLen(buf, 8);
316 }
317 
325 void consoleWriteInt32(uint32_t value)
326 {
327  char buf[12];
328  int i = 11;
329 
330  buf[i] = 0;
331  do
332  {
333  buf[--i] = '0' + (value % 10);
334  value /= 10;
335  }
336  while (value);
337 
338  consoleWriteString(buf + i);
339 }
340 
348 void consoleWriteHex16(uint16_t value)
349 {
350  char buf[4];
351  int i;
352 
353  for (i = 3; i >= 0; i--)
354  {
355  buf[i] = hexTable[value & 0xF];
356  value >>= 4;
357  }
358 
359  consoleWriteString("0x");
360  consoleWriteStringLen(buf, 4);
361 }
362 
371 bool consoleSetCursorPos(uint8_t x, uint8_t y)
372 {
373  if (x >= VGA_WIDTH || y >= VGA_HEIGHT)
374  return false;
375 
376  cursorX = x;
377  cursorY = y;
378 
379  return true;
380 }
381 
389 {
390  return (cursorY << 16) | cursorX;
391 }
392 
398 {
399  return cursorX;
400 }
401 
407 {
408  return cursorY;
409 }
410 
418 {
419  uint32_t x, y;
420 
421  for (y = 1; y < VGA_HEIGHT; y++)
422  {
423  for (x = 0; x < VGA_WIDTH; x++)
424  videoTextMemory[CHAR_OFFSET(x, y-1)] = videoTextMemory[CHAR_OFFSET(x, y)];
425  }
426  for (x = 0; x < VGA_WIDTH; x++)
427  videoTextMemory[CHAR_OFFSET(x, VGA_HEIGHT - 1)] = ' ' | (consoleColor << 8);
428 }
429 
435 {
436  return VGA_HEIGHT;
437 }
438 
444 {
445  return VGA_WIDTH;
446 }
447 
454 uint32_t consoleGetSize()
455 {
456  return (VGA_HEIGHT << 16) | VGA_WIDTH;
457 }
458 
464 void consoleShowHardwareCursor(bool changed)
465 {
466  __consoleSetMiscOutputRegister(true);
467 
468  if (consoleFlags & CONFLAGS_HWCURSOR)
469  {
470  /* skip these step if only the position is going to be updated */
471  if (changed)
472  {
473  outb(0x3D4, 0x0A);
474  outb(0x3D5, 0x00);
475  }
476 
477  uint32_t indexPos = CHAR_OFFSET(cursorHardwareX, cursorHardwareY);
478 
479  outb(0x3D4, 0x0F);
480  outb(0x3D5, indexPos & 0xFF);
481  outb(0x3D4, 0x0E);
482  outb(0x3D5, (indexPos >> 8) & 0xFF);
483  }
484  else
485  {
486  /* see http://www.osdever.net/FreeVGA/vga/crtcreg.htm#0A */
487  outb(0x3D4, 0x0A);
488  outb(0x3D5, 0x10);
489  }
490 }
491 
498 void consoleSetHardwareCursor(uint8_t x, uint8_t y)
499 {
500  cursorHardwareX = x;
501  cursorHardwareY = y;
502 
503  if (consoleFlags & CONFLAGS_HWCURSOR)
505 }
506 
514 {
515  return (cursorHardwareY << 16) | cursorHardwareX;
516 }
517 
518 extern uint8_t vga_latin1[256][16];
519 
527 {
528  uint32_t i;
529 
530  outw(0x03ce, 0x5);
531  outw(0x03ce, 0x0406);
532  outw(0x03c4, 0x0402);
533  outw(0x03c4, 0x0604);
534 
535  /*
536  * Characters can have a size up to 8x32. The memory always has the
537  * same size independent of the selected font size. The additional
538  * bytes are simply not used.
539  */
540  for (i = 0; i < 256; i++)
541  memcpy(videoFontMemory + i * 32, &vga_latin1[i], 16);
542 
543  outw(0x03c4, 0x0302);
544  outw(0x03c4, 0x0204);
545  outw(0x03ce, 0x1005);
546  outw(0x03ce, 0x0E06);
547 }
548 
554 void consoleSetFlags(uint32_t flags)
555 {
556  consoleFlags = flags;
558 }
559 
564 uint32_t consoleGetFlags()
565 {
566  return consoleFlags;
567 }
568 
589 void consoleSystemFailure(const char **lines, uint32_t numArgs, uint32_t *args, struct taskContext *context)
590 {
593  consoleClear();
594 
595  /* print the title and text lines */
596  if (lines)
597  {
598  if (*lines)
599  {
600  size_t length = stringLength(*lines);
601  consoleSetCursorPos((length < VGA_WIDTH) ? ((VGA_WIDTH - length) / 2) : 0, 2);
603  consoleWriteString(*lines);
605  consoleWriteString("\n\n");
606  lines++;
607  }
608 
609  while (*lines)
610  consoleWriteString(*lines++);
611  consoleWriteString("\n\n");
612  }
613 
614  if (numArgs && args)
615  {
616  uint32_t i;
617  for (i = 0; i < numArgs; i++, args++)
618  {
619  consoleWriteString(" Exception argument ");
621  consoleWriteString(": ");
622  consoleWriteHex32(*args);
623  consoleWriteString("\n");
624  }
625  consoleWriteString("\n");
626  }
627 
628  if (context)
629  {
630  consoleWriteString(" Registers:\n");
631  consoleWriteString(" cr3 = ");
632  consoleWriteHex32(context->cr3);
633  consoleWriteString(", eip = ");
634  consoleWriteHex32(context->eip);
635  consoleWriteString(", efl = ");
636  consoleWriteHex32(context->eflags);
637  consoleWriteString("\n eax = ");
638  consoleWriteHex32(context->eax);
639  consoleWriteString(", ecx = ");
640  consoleWriteHex32(context->ecx);
641  consoleWriteString(", edx = ");
642  consoleWriteHex32(context->edx);
643  consoleWriteString(", ebx = ");
644  consoleWriteHex32(context->ebx);
645  consoleWriteString("\n esp = ");
646  consoleWriteHex32(context->esp);
647  consoleWriteString(", ebp = ");
648  consoleWriteHex32(context->ebp);
649  consoleWriteString(", esi = ");
650  consoleWriteHex32(context->esi);
651  consoleWriteString(", edi = ");
652  consoleWriteHex32(context->edi);
653  consoleWriteString("\n\n");
654 
655  consoleWriteString(" Segments:\n");
656  consoleWriteString(" es = ");
657  consoleWriteHex32(context->es);
658  consoleWriteString(", cs = ");
659  consoleWriteHex32(context->cs);
660  consoleWriteString(", ss = ");
661  consoleWriteHex32(context->ss);
662  consoleWriteString("\n ds = ");
663  consoleWriteHex32(context->ds);
664  consoleWriteString(", fs = ");
665  consoleWriteHex32(context->fs);
666  consoleWriteString(", gs = ");
667  consoleWriteHex32(context->gs);
668  consoleWriteString("\n\n");
669  }
670 
671  /* halt processor, this function will never return */
672  debugHalt();
673 }
void consoleScrollUp()
Scroll the console up one line.
Definition: console.c:417
uint32_t ebx
Definition: context.h:55
void consoleWriteStringMax(const char *str, size_t len)
Write a nullterminated string or a maximum of len characters.
Definition: console.c:287
uint32_t consoleGetCursorPosY()
Get Y position of the text cursor.
Definition: console.c:406
void consoleWriteRawLen(const uint16_t *data, size_t count)
Write raw data with a fixed size to the console.
Definition: console.c:269
uint32_t consoleGetSize()
Returns the packed size of the console.
Definition: console.c:454
#define CHAR_OFFSET(x, y)
Definition: console.c:35
void debugHalt()
Definition: util.h:53
uint8_t consoleGetColorForeground()
Get current foreground color.
Definition: console.c:134
uint16_t fs
Definition: context.h:69
uint16_t cs
Definition: context.h:63
#define MAKE_COLOR(foreground, background)
Definition: console.h:78
uint32_t eflags
Definition: context.h:50
void consoleShowHardwareCursor(bool changed)
Show / hide blinking hardware cursor.
Definition: console.c:464
#define UNUSED
Definition: util.h:39
uint32_t ecx
Definition: context.h:53
uint32_t edx
Definition: context.h:54
void consoleWriteInt32(uint32_t value)
Write a 32 bit integer as decimal value on the console.
Definition: console.c:325
uint32_t consoleGetHardwareCursor()
Get packed position of the hardware cursor.
Definition: console.c:513
void outb(uint16_t port, uint8_t val)
Definition: io.h:35
void consoleSetFont()
Load a custom font supporting latin1 characters.
Definition: console.c:526
uint32_t stringLength(const char *str)
Returns the length of a nullterminated string.
Definition: util.c:37
uint8_t consoleGetWidth()
Returns the width (text cols) of the console.
Definition: console.c:443
void physMemProtectBootEntry(uint32_t addr, uint32_t length)
Marks all pages within a memory range as reserved and adds them to the boot map.
Definition: physmem.c:259
uint8_t inb(uint16_t port)
Definition: io.h:50
uint8_t vga_latin1[256][16]
Definition: vgafont.c:30
uint32_t eax
Definition: context.h:52
void consoleInit()
Initializes the console.
Definition: console.c:79
#define RAW_CHAR_CHR(raw)
Definition: console.h:95
#define VGA_WIDTH
Definition: console.c:33
uint32_t consoleGetCursorPosX()
Get X position of the text cursor.
Definition: console.c:397
void consoleSetColor(uint8_t color)
Set the text and background color of the console.
Definition: console.c:113
uint32_t esi
Definition: context.h:58
#define VGA_HEIGHT
Definition: console.c:34
uint8_t consoleGetHeight()
Returns the height (text rows) of the console.
Definition: console.c:434
uint8_t consoleGetColorBackground()
Get current background color.
Definition: console.c:143
void consolePutCharRaw(uint16_t chr)
Write a raw character and color on the console.
Definition: console.c:208
uint32_t cr3
Definition: context.h:48
void consoleWriteHex32(uint32_t value)
Write a 32 bit integer as hex value on the console.
Definition: console.c:303
void consoleClear()
Clear the screen contents.
Definition: console.c:90
uint8_t consoleGetColor()
Get current color.
Definition: console.c:124
uint32_t eip
Definition: context.h:49
void * memcpy(void *destination, const void *source, size_t num)
Copies a block of memory from source to destination.
Definition: util.c:141
void consoleSetHardwareCursor(uint8_t x, uint8_t y)
Set the position of the hardware cursor.
Definition: console.c:498
uint16_t gs
Definition: context.h:71
void consoleSystemFailure(const char **lines, uint32_t numArgs, uint32_t *args, struct taskContext *context)
Print a system failure message and halts the system.
Definition: console.c:589
void consoleWriteHex16(uint16_t value)
Write a 16 bit integer as hex value on the console.
Definition: console.c:348
void consoleWriteString(const char *str)
Write a C string to the console.
Definition: console.c:240
uint32_t consoleGetCursorPos()
Get packed position of the text cursor.
Definition: console.c:388
void consoleWriteStringLen(const char *str, size_t len)
Write a string with a fixed size to the console.
Definition: console.c:254
bool consoleSetCursorPos(uint8_t x, uint8_t y)
Set the position of the text cursor.
Definition: console.c:371
uint16_t ds
Definition: context.h:67
void consoleSetFlags(uint32_t flags)
Set console flags.
Definition: console.c:554
uint16_t es
Definition: context.h:61
void consoleEchoChar(char chr)
Echo keyboard input on the console.
Definition: console.c:193
uint32_t edi
Definition: context.h:59
uint16_t ss
Definition: context.h:65
uint32_t ebp
Definition: context.h:57
uint32_t value
Definition: paging.h:55
void outw(uint16_t port, uint16_t val)
Definition: io.h:40
uint32_t esp
Definition: context.h:56
void consolePutChar(char chr)
Write a character on the console.
Definition: console.c:156
uint32_t consoleGetFlags()
Get console flags.
Definition: console.c:564