The Pedigree Project  0.1
panic.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/panic.h"
21 #include "pedigree/kernel/Log.h"
22 #include "pedigree/kernel/Service.h"
23 #include "pedigree/kernel/ServiceFeatures.h"
24 #include "pedigree/kernel/ServiceManager.h"
25 #include "pedigree/kernel/debugger/DebuggerIO.h"
26 #include "pedigree/kernel/debugger/LocalIO.h"
27 #include "pedigree/kernel/debugger/SerialIO.h"
28 #include "pedigree/kernel/graphics/GraphicsService.h"
29 #include "pedigree/kernel/machine/Display.h"
30 #include "pedigree/kernel/machine/Machine.h"
31 #include "pedigree/kernel/processor/Processor.h"
32 #include "pedigree/kernel/processor/types.h"
33 #include "pedigree/kernel/utilities/StaticString.h"
34 #include "pedigree/kernel/utilities/String.h"
35 #include "pedigree/kernel/utilities/utility.h"
36 
37 static size_t newlineCount(const char *pString)
38 {
39  size_t nNewlines = 0;
40  while (*pString != '\0')
41  if (*pString++ == '\n')
42  ++nNewlines;
43 
44  return nNewlines;
45 }
46 
47 // TODO: We might want a separate parameter for a stacktrace/register dump
48 static void _panic(const char *msg, DebuggerIO *pScreen)
49 {
50  static HugeStaticString panic_output;
51  panic_output.clear();
52 
53  panic_output.append("PANIC: ");
54  panic_output.append(msg);
55 
56  // write the final string to the screen
57  pScreen->drawString(panic_output, 0, 0, DebuggerIO::Red, DebuggerIO::Black);
58 
59  size_t nLines = newlineCount(panic_output) + 2;
60 
61  Log &log = Log::instance();
62  Log::SeverityLevel level;
63  static NormalStaticString Line;
64 
65  size_t iEntry = 0, iUsedEntries = 0;
66  if ((pScreen->getHeight() - nLines) <
68  iEntry = log.getStaticEntryCount() + log.getDynamicEntryCount() -
69  (pScreen->getHeight() - nLines) + 1;
70  bool bPrintThisLine = false;
71  for (; iEntry < (log.getStaticEntryCount() + log.getDynamicEntryCount());
72  iEntry++)
73  {
74  if (iEntry < log.getStaticEntryCount())
75  {
76  const Log::StaticLogEntry &entry = log.getStaticEntry(iEntry);
77 
78  // level = entry.severity;
79  // if( level == Log::Fatal || level == Log::Error )
80  // {
81  Line.clear();
82  Line.append("[");
83  Line.append(entry.timestamp, 10, 8, '0');
84  Line.append("] ");
85  Line.append(entry.str);
86  Line.append("\n");
87 
88  bPrintThisLine = true;
89  // }
90  }
91  else
92  {
93  const Log::DynamicLogEntry &entry = log.getDynamicEntry(iEntry);
94  level = entry.severity;
95 
96  // if( level == Log::Fatal || level == Log::Error )
97  // {
98  Line.clear();
99  Line.append("[");
100  Line.append(entry.timestamp, 10, 8, '0');
101  Line.append("] ");
102  Line.append(entry.str);
103  Line.append("\n");
104 
105  bPrintThisLine = true;
106  // }
107  }
108 
109  // print the line
110  if (bPrintThisLine == true)
111  {
112  ++iUsedEntries;
113  pScreen->drawString(
114  Line, nLines + iUsedEntries, 0, DebuggerIO::White,
115  DebuggerIO::Black);
116  bPrintThisLine = false;
117  }
118  }
119 }
120 
121 void panic(const char *msg)
122 {
123  static String graphicsService("graphics");
124 
126 
127  // Drop out of whatever graphics mode we were in
129  ByteSet(&provider, 0, sizeof(provider));
130  provider.bTextModes = true;
131 
132  ServiceFeatures *pFeatures =
133  ServiceManager::instance().enumerateOperations(graphicsService);
134  Service *pService = ServiceManager::instance().getService(graphicsService);
135  bool bSuccess = false;
136  if (pFeatures && pFeatures->provides(ServiceFeatures::probe))
137  if (pService)
138  bSuccess = pService->serve(
139  ServiceFeatures::probe, reinterpret_cast<void *>(&provider),
140  sizeof(provider));
141 
142  if (bSuccess && !provider.bTextModes)
143  provider.pDisplay->setScreenMode(0);
144 
145 #ifdef MULTIPROCESSOR
146  Machine::instance().stopAllOtherProcessors();
147 #endif
148 
149  /*
150  * I/O implementations.
151  */
152  SerialIO serialIO(Machine::instance().getSerial(0));
153 
154  DebuggerIO *pInterfaces[2] = {0};
155 
156  int nInterfaces = 0;
157  if (Machine::instance()
158  .getNumVga()) // Not all machines have "VGA", so handle that
159  {
160  static LocalIO localIO(
161  Machine::instance().getVga(0), Machine::instance().getKeyboard());
162 #ifdef DONT_LOG_TO_SERIAL
163  pInterfaces[0] = &localIO;
164  nInterfaces = 1;
165 #else
166  pInterfaces[0] = &localIO;
167  pInterfaces[1] = &serialIO;
168  nInterfaces = 2;
169 #endif
170  }
171 #ifndef DONT_LOG_TO_SERIAL
172  else
173  {
174  pInterfaces[0] = &serialIO;
175  nInterfaces = 1;
176  }
177 #endif
178 
179  for (int nIFace = 0; nIFace < nInterfaces; nIFace++)
180  _panic(msg, pInterfaces[nIFace]);
181 
182  // Halt the processor
183  while (1)
184  Processor::halt();
185 }
StaticString< LOG_LENGTH > str
Definition: Log.h:245
the kernel&#39;s log
Definition: Log.h:166
size_t getStaticEntryCount() const
Definition: Log.cc:225
Definition: String.h:49
SeverityLevel severity
Definition: Log.h:243
virtual bool provides(Type service)
const StaticLogEntry & getStaticEntry(size_t n) const
Definition: Log.cc:235
const DynamicLogEntry & getDynamicEntry(size_t n) const
Definition: Log.cc:240
unsigned int timestamp
Definition: Log.h:241
size_t getDynamicEntryCount() const
Definition: Log.cc:230
SeverityLevel
Definition: Log.h:180
static void setInterrupts(bool bEnable)
static void halt()
virtual void drawString(const char *str, size_t row, size_t col, Colour foreColour, Colour backColour)=0
static EXPORTED_PUBLIC Log & instance()
Definition: Log.cc:108
Service * getService(const String &serviceName)
virtual bool serve(ServiceFeatures::Type type, void *pData, size_t dataLen)=0
void panic(const char *msg)
Definition: panic.cc:121
ServiceFeatures * enumerateOperations(const String &serviceName)
virtual bool setScreenMode(ScreenMode sm)
Definition: Display.cc:110