Bind GPU to screen in kernel, to allow boot errors to show up on the screen before an OS binds it.

Set resolution and depth to max in GPU's crash display (bluescreen).
This commit is contained in:
Florian Nücke 2014-05-31 01:02:42 +02:00
parent 6ef0e5d26c
commit 22d020004c
2 changed files with 51 additions and 40 deletions

View File

@ -538,28 +538,35 @@ sandbox.unicode = libunicode
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
local function bootstrap() local function bootstrap()
local function tryLoadFrom(address) function boot_invoke(address, method, ...)
function boot_invoke(method, ...) local result = table.pack(pcall(invoke, component, true, address, method, ...))
local result = table.pack(pcall(invoke, component, true, address, method, ...)) if not result[1] then
if not result[1] then return nil, result[2]
return nil, result[2] else
else return table.unpack(result, 2, result.n)
return table.unpack(result, 2, result.n)
end
end end
local handle, reason = boot_invoke("open", "/init.lua") end
do
local screen = libcomponent.list("screen")()
local gpu = libcomponent.list("gpu")()
if gpu and screen then
boot_invoke(gpu, "bind", screen)
end
end
local function tryLoadFrom(address)
local handle, reason = boot_invoke(address, "open", "/init.lua")
if not handle then if not handle then
return nil, reason return nil, reason
end end
local buffer = "" local buffer = ""
repeat repeat
local data, reason = boot_invoke("read", handle, math.huge) local data, reason = boot_invoke(address, "read", handle, math.huge)
if not data and reason then if not data and reason then
return nil, reason return nil, reason
end end
buffer = buffer .. (data or "") buffer = buffer .. (data or "")
until not data until not data
boot_invoke("close", handle) boot_invoke(address, "close", handle)
return load(buffer, "=init", "t", sandbox) return load(buffer, "=init", "t", sandbox)
end end
local init, reason local init, reason

View File

@ -2,13 +2,14 @@ package li.cil.oc.server.component
import li.cil.oc.Settings import li.cil.oc.Settings
import li.cil.oc.api.Network import li.cil.oc.api.Network
import li.cil.oc.api.component.TextBuffer
import li.cil.oc.api.component.TextBuffer.ColorDepth import li.cil.oc.api.component.TextBuffer.ColorDepth
import li.cil.oc.api.network._ import li.cil.oc.api.network._
import li.cil.oc.common.component import li.cil.oc.common.component
import li.cil.oc.util.PackedColor import li.cil.oc.util.PackedColor
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.StatCollector import net.minecraft.util.StatCollector
import li.cil.oc.api.component.TextBuffer import scala.collection.convert.WrapAsScala._
abstract class GraphicsCard extends component.ManagedComponent { abstract class GraphicsCard extends component.ManagedComponent {
val node = Network.newNode(this, Visibility.Neighbors). val node = Network.newNode(this, Visibility.Neighbors).
@ -233,36 +234,39 @@ abstract class GraphicsCard extends component.ManagedComponent {
override def onMessage(message: Message) { override def onMessage(message: Message) {
super.onMessage(message) super.onMessage(message)
if (message.name == "computer.stopped" && node.isNeighborOf(message.source)) { if (message.name == "computer.stopped" && node.isNeighborOf(message.source)) {
screenInstance match { screen(s => {
case Some(buffer) => buffer.synchronized { val (gmw, gmh) = maxResolution
val w = buffer.getWidth val smw = s.getMaximumWidth
val h = buffer.getHeight val smh = s.getMaximumHeight
buffer.setForegroundColor(0xFFFFFF) s.setResolution(math.min(gmw, smw), math.min(gmh, smh))
message.source.host match { s.setColorDepth(ColorDepth.values.apply(math.min(maxDepth.ordinal, s.getMaximumColorDepth.ordinal)))
case machine: machine.Machine if machine.lastError != null => s.setForegroundColor(0xFFFFFF)
if (buffer.getColorDepth.ordinal > ColorDepth.OneBit.ordinal) buffer.setBackgroundColor(0x0000FF) val w = s.getWidth
else buffer.setBackgroundColor(0x000000) val h = s.getHeight
buffer.fill(0, 0, w, h, ' ') message.source.host match {
try { case machine: machine.Machine if machine.lastError != null =>
val message = "Unrecoverable error:\n" + StatCollector.translateToLocal(machine.lastError) + "\n" if (s.getColorDepth.ordinal > ColorDepth.OneBit.ordinal) s.setBackgroundColor(0x0000FF)
val wrapRegEx = s"(.{1,${math.max(1, w - 2)}})\\s".r else s.setBackgroundColor(0x000000)
val lines = wrapRegEx.replaceAllIn(message, m => m.group(1) + "\n").lines.toArray s.fill(0, 0, w, h, ' ')
for ((line, idx) <- lines.zipWithIndex) { try {
val col = (w - line.length) / 2 val message = "Unrecoverable error:\n" + StatCollector.translateToLocal(machine.lastError) + "\n"
val row = (h - lines.length) / 2 + idx val wrapRegEx = s"(.{1,${math.max(1, w - 2)}})\\s".r
buffer.set(col, row, line, false) val lines = wrapRegEx.replaceAllIn(message, m => m.group(1) + "\n").lines.toArray
} for ((line, idx) <- lines.zipWithIndex) {
val col = (w - line.length) / 2
val row = (h - lines.length) / 2 + idx
s.set(col, row, line, false)
} }
catch { }
case t: Throwable => t.printStackTrace() catch {
} case t: Throwable => t.printStackTrace()
case _ => }
buffer.setBackgroundColor(0x000000) case _ =>
buffer.fill(0, 0, w, h, ' ') s.setBackgroundColor(0x000000)
} s.fill(0, 0, w, h, ' ')
} }
case _ => null // For screen()
} })
} }
} }