gfx_test: Set our own framebuffers up, update README
Use GMA.Setup_Default_FB() to allocate framebuffers in the stolen memory. To help with setups where we can't unload the i915 driver, back up and restore the current GTT setup and framebuffer contents. Also add a wrapper script and update the README. Change-Id: I10790d35d38b7b211f41b2452f6d2baf17372e31 Signed-off-by: Nico Huber <nico.h@gmx.de> Reviewed-on: https://review.coreboot.org/20604 Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
This commit is contained in:
parent
42fb2d065d
commit
3b654a0991
35
README.md
35
README.md
|
@ -45,11 +45,15 @@ in `configs/`, e.g.:
|
|||
or overwrite the config filename by specifying `cnf=<configfile>` on
|
||||
the make command line.
|
||||
|
||||
By default most debug messages won't be compiled into the binary. To
|
||||
include them into the build, set `DEBUG=1` on the command line or in
|
||||
your `.config`.
|
||||
|
||||
Let's install *libhwbase*. We'll need `configs/linux` to build regular
|
||||
Linux executables:
|
||||
|
||||
$ cd libhwbase
|
||||
$ make cnf=configs/linux install
|
||||
$ make DEBUG=1 cnf=configs/linux install
|
||||
|
||||
By default this installs into a new subdirectory `dest`. You can however
|
||||
overwrite this decision by specifying `DESTDIR=`.
|
||||
|
@ -65,7 +69,7 @@ The makefile knows an additional target `gfx_test` to build a small
|
|||
Linux test application:
|
||||
|
||||
$ cd ../libgfxinit
|
||||
$ make cnf=configs/sandybridge gfx_test
|
||||
$ make DEBUG=1 cnf=configs/sandybridge gfx_test
|
||||
|
||||
The resulting binary is `build/gfx_test`.
|
||||
|
||||
|
@ -73,20 +77,19 @@ The resulting binary is `build/gfx_test`.
|
|||
Testing libgfxinit on Linux
|
||||
===========================
|
||||
|
||||
In its current state `gfx_test` doesn't know how to set up a frame-
|
||||
buffer. It just assumes that enough memory is mapped. This is known
|
||||
to work well, after running the VBIOS but before the Linux driver
|
||||
*i915* took over (e.g. when booting with `nomodeset` in the kernel
|
||||
command line or with *i915* blacklisted). After running *i915* it
|
||||
only works by chance.
|
||||
`gfx_test` sets up its own framebuffer in the *stolen memory*. It
|
||||
backs any current framebuffer mapping and contents up first and re-
|
||||
stores it before exiting. This works somehow even while the *i915*
|
||||
driver is running. A wrapper script `gfxtest/gfx_test.sh` is pro-
|
||||
vided to help with the setup. It switches to a text console first
|
||||
and tries to unload the *i915* driver. But ignores failures to do
|
||||
so (it won't work if you still have any application running that
|
||||
uses the gfx driver, e.g. an X server).
|
||||
|
||||
When running `gfx_test` (as root), it will access the graphics hard-
|
||||
ware through the sysfs PCI interface. The path is
|
||||
|
||||
/sys/devices/pci0000:00/0000:00:02.0/
|
||||
|
||||
for all supported platforms.
|
||||
# gfxtest/gfx_test.sh
|
||||
|
||||
If you chose the right config above, you should be presented with a
|
||||
nice test image. However, `gfx_test` is one-way only: The graphics
|
||||
hardware will stay in this state, until another driver takes over.
|
||||
nice test image. But please be prepared that your console might be
|
||||
stuck in that state afterwards. You can try to run it with *i915*
|
||||
deactivated then (e.g. when booting with `nomodeset` in the kernel
|
||||
command line or with *i915* blacklisted) and loading it afterwards.
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
usage="Usage: $0 [seconds]\n"
|
||||
|
||||
err_msgs=
|
||||
command -v chvt >/dev/null || err_msgs="${err_msgs}"'Need `chvt`\n'
|
||||
command -v openvt >/dev/null || err_msgs="${err_msgs}"'Need `openvt`\n'
|
||||
command -v fgconsole >/dev/null || err_msgs="${err_msgs}"'Need `fgconsole`\n'
|
||||
[ -n "$err_msgs" ] && err_msgs="${err_msgs}"'e.g. install the `kbd` package\n'
|
||||
|
||||
[ -x build/gfx_test ] || \
|
||||
err_msgs="${err_msgs}"'Please run from *libgfxinit* source dir and build `gfx_test` first.\n'
|
||||
|
||||
[ "$#" -gt 1 ] && err_msgs="${err_msgs}${usage}"
|
||||
|
||||
if [ -n "$err_msgs" ]; then
|
||||
printf "$err_msgs"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$#" -lt 1 ]; then
|
||||
# default duration of 5s
|
||||
set 5
|
||||
fi
|
||||
|
||||
reload_i915=0
|
||||
prepare_vt() {
|
||||
# switch VT, we might be in X
|
||||
orig_vt=`fgconsole`
|
||||
openvt -s -- true
|
||||
|
||||
# poll until the VT switch is done
|
||||
while [ `fgconsole` -eq $orig_vt ]; do :; done
|
||||
|
||||
# take i915 out of charge
|
||||
echo 0 >/sys/devices/virtual/vtconsole/vtcon1/bind
|
||||
|
||||
# try unloading it
|
||||
if lsmod | grep -q i915 && modprobe -r i915 >/dev/null 2>&1; then
|
||||
reload_i915=1
|
||||
fi
|
||||
}
|
||||
|
||||
restore_vt() {
|
||||
# reload i915
|
||||
if [ $reload_i915 -eq 1 ]; then
|
||||
modprobe i915
|
||||
fi
|
||||
|
||||
# put i915 back in charge
|
||||
echo 1 >/sys/devices/virtual/vtconsole/vtcon1/bind
|
||||
|
||||
# return to original VT
|
||||
chvt $orig_vt
|
||||
}
|
||||
|
||||
prepare_vt
|
||||
|
||||
build/gfx_test "$@" || true
|
||||
|
||||
restore_vt
|
|
@ -2,10 +2,12 @@ with Ada.Unchecked_Conversion;
|
|||
with Ada.Command_Line;
|
||||
with Interfaces.C;
|
||||
|
||||
with HW.Time;
|
||||
with HW.Debug;
|
||||
with HW.PCI.Dev;
|
||||
with HW.MMIO_Range;
|
||||
with HW.GFX.GMA;
|
||||
with HW.GFX.GMA.Config;
|
||||
with HW.GFX.GMA.Display_Probing;
|
||||
|
||||
package body HW.GFX.GMA.GFX_Test
|
||||
|
@ -14,6 +16,32 @@ is
|
|||
|
||||
package Dev is new PCI.Dev (PCI.Address'(0, 2, 0));
|
||||
|
||||
type GTT_PTE_Type is mod 2 ** (Config.GTT_PTE_Size * 8);
|
||||
type GTT_Registers_Type is array (GTT_Range) of GTT_PTE_Type;
|
||||
package GTT is new MMIO_Range
|
||||
(Base_Addr => 0,
|
||||
Element_T => GTT_PTE_Type,
|
||||
Index_T => GTT_Range,
|
||||
Array_T => GTT_Registers_Type);
|
||||
|
||||
GTT_Backup : GTT_Registers_Type;
|
||||
|
||||
procedure Backup_GTT
|
||||
is
|
||||
begin
|
||||
for Idx in GTT_Range loop
|
||||
GTT.Read (GTT_Backup (Idx), Idx);
|
||||
end loop;
|
||||
end Backup_GTT;
|
||||
|
||||
procedure Restore_GTT
|
||||
is
|
||||
begin
|
||||
for Idx in GTT_Range loop
|
||||
GTT.Write (Idx, GTT_Backup (Idx));
|
||||
end loop;
|
||||
end Restore_GTT;
|
||||
|
||||
type Pixel_Type is record
|
||||
Red : Byte;
|
||||
Green : Byte;
|
||||
|
@ -46,7 +74,27 @@ is
|
|||
|
||||
package Screen is new MMIO_Range (0, Word32, Screen_Index, Screen_Type);
|
||||
|
||||
Pipes : GMA.Pipe_Configs;
|
||||
Screen_Backup : Screen_Type;
|
||||
|
||||
procedure Backup_Screen (FB : Framebuffer_Type)
|
||||
is
|
||||
First : constant Screen_Index := Natural (FB.Offset) / 4;
|
||||
Last : constant Screen_Index := First + Natural (FB_Size (FB)) / 4 - 1;
|
||||
begin
|
||||
for Idx in Screen_Index range First .. Last loop
|
||||
Screen.Read (Screen_Backup (Idx), Idx);
|
||||
end loop;
|
||||
end Backup_Screen;
|
||||
|
||||
procedure Restore_Screen (FB : Framebuffer_Type)
|
||||
is
|
||||
First : constant Screen_Index := Natural (FB.Offset) / 4;
|
||||
Last : constant Screen_Index := First + Natural (FB_Size (FB)) / 4 - 1;
|
||||
begin
|
||||
for Idx in Screen_Index range First .. Last loop
|
||||
Screen.Write (Idx, Screen_Backup (Idx));
|
||||
end loop;
|
||||
end Restore_Screen;
|
||||
|
||||
function Fill
|
||||
(X, Y : Natural;
|
||||
|
@ -113,11 +161,14 @@ is
|
|||
Offset := Offset + Word32 (FB.Stride * FB.Height * 4);
|
||||
end Calc_Framebuffer;
|
||||
|
||||
Pipes : GMA.Pipe_Configs;
|
||||
|
||||
procedure Prepare_Configs
|
||||
is
|
||||
use type HW.GFX.GMA.Port_Type;
|
||||
|
||||
Offset : Word32 := 0;
|
||||
Success : Boolean;
|
||||
begin
|
||||
GMA.Display_Probing.Scan_Ports (Pipes);
|
||||
|
||||
|
@ -127,12 +178,27 @@ is
|
|||
(FB => Pipes (Pipe).Framebuffer,
|
||||
Mode => Pipes (Pipe).Mode,
|
||||
Offset => Offset);
|
||||
GMA.Setup_Default_FB
|
||||
(FB => Pipes (Pipe).Framebuffer,
|
||||
Clear => False,
|
||||
Success => Success);
|
||||
if not Success then
|
||||
Pipes (Pipe).Port := GMA.Disabled;
|
||||
end if;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
GMA.Dump_Configs (Pipes);
|
||||
end Prepare_Configs;
|
||||
|
||||
procedure Print_Usage
|
||||
is
|
||||
begin
|
||||
Debug.Put_Line
|
||||
("Usage: " & Ada.Command_Line.Command_Name & " <delay seconds>");
|
||||
Debug.New_Line;
|
||||
end Print_Usage;
|
||||
|
||||
procedure Main
|
||||
is
|
||||
use type HW.GFX.GMA.Port_Type;
|
||||
|
@ -141,12 +207,21 @@ is
|
|||
|
||||
Res_Addr : Word64;
|
||||
|
||||
Delay_S : Natural;
|
||||
|
||||
Dev_Init,
|
||||
Initialized : Boolean;
|
||||
|
||||
function iopl (level : Interfaces.C.int) return Interfaces.C.int;
|
||||
pragma Import (C, iopl, "iopl");
|
||||
begin
|
||||
if Ada.Command_Line.Argument_Count /= 1 then
|
||||
Print_Usage;
|
||||
return;
|
||||
end if;
|
||||
|
||||
Delay_S := Natural'Value (Ada.Command_Line.Argument (1));
|
||||
|
||||
if iopl (3) /= 0 then
|
||||
Debug.Put_Line ("Failed to change i/o privilege level.");
|
||||
return;
|
||||
|
@ -158,6 +233,13 @@ is
|
|||
return;
|
||||
end if;
|
||||
|
||||
Dev.Map (Res_Addr, PCI.Res0, Offset => Config.GTT_Offset);
|
||||
if Res_Addr = 0 then
|
||||
Debug.Put_Line ("Failed to map PCI resource0.");
|
||||
return;
|
||||
end if;
|
||||
GTT.Set_Base_Address (Res_Addr);
|
||||
|
||||
Dev.Map (Res_Addr, PCI.Res2, WC => True);
|
||||
if Res_Addr = 0 then
|
||||
Debug.Put_Line ("Failed to map PCI resource2.");
|
||||
|
@ -170,17 +252,29 @@ is
|
|||
Success => Initialized);
|
||||
|
||||
if Initialized then
|
||||
Backup_GTT;
|
||||
|
||||
Prepare_Configs;
|
||||
|
||||
GMA.Update_Outputs (Pipes);
|
||||
|
||||
for Pipe in GMA.Pipe_Index loop
|
||||
if Pipes (Pipe).Port /= GMA.Disabled then
|
||||
Backup_Screen (Pipes (Pipe).Framebuffer);
|
||||
Test_Screen
|
||||
(Framebuffer => Pipes (Pipe).Framebuffer,
|
||||
Pipe => Pipe);
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
Time.M_Delay (Delay_S * 1_000);
|
||||
|
||||
for Pipe in GMA.Pipe_Index loop
|
||||
if Pipes (Pipe).Port /= GMA.Disabled then
|
||||
Restore_Screen (Pipes (Pipe).Framebuffer);
|
||||
end if;
|
||||
end loop;
|
||||
Restore_GTT;
|
||||
end if;
|
||||
end Main;
|
||||
|
||||
|
|
Loading…
Reference in New Issue