The Pedigree Project  0.1
BootIO.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "pedigree/kernel/core/BootIO.h"
21 #include "pedigree/kernel/Log.h"
22 #include "pedigree/kernel/machine/Machine.h"
23 #include "pedigree/kernel/machine/Serial.h"
24 #include "pedigree/kernel/machine/Vga.h"
25 #include "pedigree/kernel/processor/types.h"
26 #include "pedigree/kernel/utilities/StaticString.h"
27 
28 BootIO::BootIO() : m_CursorX(0), m_CursorY(0)
29 {
30 }
31 
33 {
34 }
35 
37 {
38  Vga *pVga = Machine::instance().getVga(0);
39  if (pVga)
40  {
41  pVga->setLargestTextMode();
42  uint16_t *pFramebuffer = *pVga;
43  if (pFramebuffer != 0)
44  for (size_t i = 0; i < pVga->getNumRows() * pVga->getNumCols(); i++)
45  pFramebuffer[i] = 0;
46  }
47 
48  HugeStaticString str;
49  str += "BootIO is initialized!\n";
50  write(str, Black, Black);
51 }
52 
53 template <class T>
54 void BootIO::write(T &str, Colour foreColour, Colour backColour)
55 {
56  for (size_t i = 0; i < str.length(); i++)
57  putCharVga(str[i], foreColour, backColour);
58  if (Log::instance().echoToSerial())
59  {
60 #ifndef SERIAL_IS_FILE
61  startColour(Machine::instance().getSerial(0), foreColour, backColour);
62 #endif
63  for (size_t j = 0; j < str.length(); j++)
64  Machine::instance().getSerial(0)->write(str[j]);
65 #ifndef SERIAL_IS_FILE
66  endColour(Machine::instance().getSerial(0));
67 #endif
68  }
69 
70 #ifdef PPC_COMMON
71  // For PPC: causes the graphics framebuffer to be updated from the text one.
72  Vga *pVga = Machine::instance().getVga(0);
73  uint16_t *pFramebuffer = *pVga;
74  pVga->pokeBuffer(reinterpret_cast<uint8_t *>(pFramebuffer), 0);
75 #endif
76 }
77 
78 void BootIO::putCharVga(const char c, Colour foreColour, Colour backColour)
79 {
80  Vga *pVga = Machine::instance().getVga(0);
81  if (pVga)
82  {
83  uint16_t *pFramebuffer = *pVga;
84  if (pFramebuffer == 0)
85  return;
86  // Backspace?
87  if (c == 0x08)
88  {
89  // Can we just move backwards? or do we have to go up?
90  if (m_CursorX)
91  m_CursorX--;
92  else
93  {
94  m_CursorX = pVga->getNumCols() - 1;
95  if (m_CursorY > 0)
96  m_CursorY--;
97  }
98 
99  // Erase the contents of the cell currently.
100  uint8_t attributeByte = (backColour << 4) | (foreColour & 0x0F);
101  pFramebuffer[m_CursorY * pVga->getNumCols() + m_CursorX] =
102  ' ' | (attributeByte << 8);
103  }
104 
105  // Tab?
106  else if (
107  c == 0x09 && (((m_CursorX + 8) & ~(8 - 1)) < pVga->getNumCols()))
108  m_CursorX = (m_CursorX + 8) & ~(8 - 1);
109 
110  // Carriage return?
111  else if (c == '\r')
112  m_CursorX = 0;
113 
114  // Newline?
115  else if (c == '\n')
116  {
117  m_CursorX = 0;
118  m_CursorY++;
119  }
120 
121  // Normal character?
122  else if (c >= ' ')
123  {
124  uint8_t attributeByte = (backColour << 4) | (foreColour & 0x0F);
125  pFramebuffer[m_CursorY * pVga->getNumCols() + m_CursorX] =
126  c | (attributeByte << 8);
127 
128  // Increment the cursor.
129  m_CursorX++;
130  }
131 
132  // Do we need to wrap?
133  if (m_CursorX >= pVga->getNumCols())
134  {
135  m_CursorX = 0;
136  m_CursorY++;
137  }
138 
139  // Get a space character with the default colour attributes.
140  uint8_t attributeByte = (Black << 4) | (White & 0x0F);
141  uint16_t blank = ' ' | (attributeByte << 8);
142  if (m_CursorY >= pVga->getNumRows())
143  {
144  for (size_t i = 0;
145  i < (pVga->getNumRows() - 1) * pVga->getNumCols(); i++)
146  pFramebuffer[i] = pFramebuffer[i + pVga->getNumCols()];
147 
148  for (size_t i = (pVga->getNumRows() - 1) * pVga->getNumCols();
149  i < (pVga->getNumRows()) * pVga->getNumCols(); i++)
150  pFramebuffer[i] = blank;
151 
152  m_CursorY = pVga->getNumRows() - 1;
153  }
154  }
155 }
156 
157 void BootIO::startColour(Serial *pSerial, Colour foreColour, Colour backColour)
158 {
159  pSerial->write("\033[");
160  switch (foreColour)
161  {
162  case Black:
163  pSerial->write("30");
164  break;
165  case Red:
166  pSerial->write("31");
167  break;
168  case Green:
169  pSerial->write("32");
170  break;
171  case Yellow:
172  pSerial->write("1;33");
173  break; // It's actually brown.
174  case Blue:
175  pSerial->write("34");
176  break;
177  case Magenta:
178  pSerial->write("35");
179  break;
180  case Cyan:
181  pSerial->write("36");
182  break;
183  case LightGrey:
184  pSerial->write("0;37");
185  break;
186  case DarkGrey:
187  pSerial->write("1;30");
188  break;
189  case LightRed:
190  pSerial->write("1;31");
191  break;
192  case LightGreen:
193  pSerial->write("1;32");
194  break;
195  case LightBlue:
196  pSerial->write("1;34");
197  break;
198  case LightMagenta:
199  pSerial->write("1;35");
200  break;
201  case LightCyan:
202  pSerial->write("1;36");
203  break;
204  case White:
205  pSerial->write("1;37");
206  break;
207  default:
208  pSerial->write('1');
209  }
210  pSerial->write(";");
211  switch (backColour)
212  {
213  case Black:
214  pSerial->write("40");
215  break;
216  case Red:
217  pSerial->write("41");
218  break;
219  case Green:
220  pSerial->write("42");
221  break;
222  case DarkGrey:
223  pSerial->write("43");
224  break; // It's actually brown.
225  case Blue:
226  pSerial->write("44");
227  break;
228  case Magenta:
229  pSerial->write("45");
230  break;
231  case Cyan:
232  pSerial->write("46");
233  break;
234  case White:
235  pSerial->write("47");
236  break;
237  default:
238  pSerial->write('1');
239  }
240  pSerial->write('m');
241 }
242 
243 void BootIO::endColour(Serial *pSerial)
244 {
245 }
246 
247 template EXPORTED_PUBLIC void BootIO::write<TinyStaticString>(
248  TinyStaticString &str, Colour foreColour, Colour backColour);
249 template EXPORTED_PUBLIC void BootIO::write<NormalStaticString>(
250  NormalStaticString &str, Colour foreColour, Colour backColour);
251 template EXPORTED_PUBLIC void BootIO::write<LargeStaticString>(
252  LargeStaticString &str, Colour foreColour, Colour backColour);
253 template EXPORTED_PUBLIC void BootIO::write<HugeStaticString>(
254  HugeStaticString &str, Colour foreColour, Colour backColour);
virtual Serial * getSerial(size_t n)=0
EXPORTED_PUBLIC void write(T &str, Colour foreColour, Colour backColour)
virtual void pokeBuffer(uint8_t *pBuffer, size_t nBufLen)=0
Colour
Definition: BootIO.h:42
virtual Vga * getVga(size_t n)=0
size_t m_CursorX
Definition: BootIO.h:86
BootIO() NOTHROW
Definition: BootIO.cc:28
static EXPORTED_PUBLIC Log & instance()
Definition: Log.cc:108
virtual bool setLargestTextMode()=0
void initialise()
Definition: BootIO.cc:36
~BootIO()
Definition: BootIO.cc:32
virtual size_t getNumRows()=0
virtual size_t getNumCols()=0