Skip to content

Commit

Permalink
x86: Add EFI framebuffer debug console
Browse files Browse the repository at this point in the history
All modern UEFI system come with the so-called Graphic Output Protocol
which provides a simple framebuffer device. This can also be used as
alternative to UART-based debug consoles. And it can replace the VGA
console which is no longer working on such systems (VGA is legacy).

As we are now filling a graphic buffer, we are in need of a console
font. The altc-8x16 we use here was taken from KBD version 2.0.4
(https://www.kernel.org/pub/linux/utils/kbd) and is licensed under
GPL-2.0-or-later. Leave a note about this also in the LICENSING file.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
  • Loading branch information
jan-kiszka committed Jul 12, 2018
1 parent 651e492 commit 790ac72
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 5 deletions.
20 changes: 17 additions & 3 deletions Documentation/debug-output.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ Possible debug outputs for x86:


- JAILHOUSE_CON_TYPE_8250 /* 8250-compatible UART (PIO or MMIO) */ - JAILHOUSE_CON_TYPE_8250 /* 8250-compatible UART (PIO or MMIO) */
- JAILHOUSE_CON_TYPE_VGA /* VGA console */ - JAILHOUSE_CON_TYPE_VGA /* VGA console */
- JAILHOUSE_CON_TYPE_EFIFB /* EFI framebuffer console */


VGA output is only available for x86. For further documentation on VGA output For further documentation on VGA output see [vga-console.md](vga-console.md).
see [vga-console.md](vga-console.md).


Possible debug outputs for arm and arm64: Possible debug outputs for arm and arm64:


Expand All @@ -42,6 +42,11 @@ Possible register distances (MMIO only, PIO is implicitly 1-byte), to be or'ed:
- JAILHOUSE_CON_REGDIST_1 /* 1-byte distance */ - JAILHOUSE_CON_REGDIST_1 /* 1-byte distance */
- JAILHOUSE_CON_REGDIST_4 /* 4-bytes distance */ - JAILHOUSE_CON_REGDIST_4 /* 4-bytes distance */


Possible framebuffer formats (EFIFB only);

- JAILHOUSE_CON_FB_1024x768 /* 1024x786 pixel, 32 bit each */
- JAILHOUSE_CON_FB_1920x1080 /* 1920x1080 pixel, 32 bit each */

### .address and .size ### .address and .size
The address member denotes the base address of the Debug console (PIO or MMIO The address member denotes the base address of the Debug console (PIO or MMIO
base address). The .size parameter is only required for MMIO. base address). The .size parameter is only required for MMIO.
Expand Down Expand Up @@ -86,6 +91,15 @@ Example configuration for MMIO based debug output on ARM (8250 UART):
.flags = JAILHOUSE_CON_MMIO_32, /* choose 32-bit MMIO access */ .flags = JAILHOUSE_CON_MMIO_32, /* choose 32-bit MMIO access */
}, },


Example configuration for EFI framebuffer debug out on x86:

.debug_console = {
.address = 0x80000000, /* framebuffer base address */
.size = 0x300000, /* 1024x786x4 */
.type = JAILHOUSE_CON_TYPE_EFIFB, /* choose the EFIFB driver */
.flags = JAILHOUSE_CON_FB_1024x768 /* format */
},

Example configuration for disabled debug output (architecture independent): Example configuration for disabled debug output (architecture independent):


.debug_console = { .debug_console = {
Expand Down Expand Up @@ -153,7 +167,7 @@ arm: none, 8250, hscif, imx, mvebu, pl011, scifa, xuartps
Similar to the hypervisor configuration, a zero value for con-divider will skip Similar to the hypervisor configuration, a zero value for con-divider will skip
initialisation of the UART interface. initialisation of the UART interface.


On x86, VGA output is not available for inmates. On x86, VGA and EFI framebuffer output are not available for inmates.


### Examples ### Examples
Example command line parameters for PIO based debug output on x86, where the Example command line parameters for PIO based debug output on x86, where the
Expand Down
5 changes: 5 additions & 0 deletions LICENSING.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ Whenever a file is provided under an additional or different license than
GPLv2, this is stated in the file header. Any file that may lack such a GPLv2, this is stated in the file header. Any file that may lack such a
header has to be considered licensed under GPLv2 (default license). header has to be considered licensed under GPLv2 (default license).


The binary font file hypervisor/arch/x86/altc-8x16 was taken from the KBD
project in version 2.0.4 (https://www.kernel.org/pub/linux/utils/kbd,
http://kbd-project.org) which is distributed under the GNU GPL version 2 or
later (SPDX identifier GPL-2.0-or-later).

If two licenses are specified in a file header, you are free to pick the one If two licenses are specified in a file header, you are free to pick the one
that suits best your particular use case. You can also continue to use the that suits best your particular use case. You can also continue to use the
file under the dual license. When choosing only one, remove the reference to file under the dual license. When choosing only one, remove the reference to
Expand Down
6 changes: 5 additions & 1 deletion hypervisor/arch/x86/Kbuild
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ ccflags-$(CONFIG_JAILHOUSE_GCOV) += -fprofile-arcs -ftest-coverage
always := lib-amd.a lib-intel.a always := lib-amd.a lib-intel.a


common-objs-y := apic.o dbg-write.o entry.o setup.o control.o mmio.o iommu.o \ common-objs-y := apic.o dbg-write.o entry.o setup.o control.o mmio.o iommu.o \
paging.o pci.o i8042.o vcpu.o vga.o ivshmem.o paging.o pci.o i8042.o vcpu.o vga.o efifb.o ivshmem.o

CFLAGS_efifb.o := -I$(src)

$(obj)/efifb.o: $(src)/altc-8x16


# units initialization order as defined by linking order: # units initialization order as defined by linking order:
# iommu, ioapic, [test-device], [cat], <generic units> # iommu, ioapic, [test-device], [cat], <generic units>
Expand Down
Binary file added hypervisor/arch/x86/altc-8x16
Binary file not shown.
4 changes: 4 additions & 0 deletions hypervisor/arch/x86/dbg-write.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <jailhouse/control.h> #include <jailhouse/control.h>
#include <jailhouse/printk.h> #include <jailhouse/printk.h>
#include <jailhouse/uart.h> #include <jailhouse/uart.h>
#include <asm/efifb.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/vga.h> #include <asm/vga.h>


Expand Down Expand Up @@ -49,5 +50,8 @@ void arch_dbg_write_init(void)
} else if (dbg_type == JAILHOUSE_CON_TYPE_VGA) { } else if (dbg_type == JAILHOUSE_CON_TYPE_VGA) {
vga_init(); vga_init();
arch_dbg_write = vga_write; arch_dbg_write = vga_write;
} else if (dbg_type == JAILHOUSE_CON_TYPE_EFIFB) {
efifb_init();
arch_dbg_write = efifb_write;
} }
} }
116 changes: 116 additions & 0 deletions hypervisor/arch/x86/efifb.c
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Jailhouse, a Linux-based partitioning hypervisor
*
* Copyright (c) Siemens AG, 2018
*
* Authors:
* Jan Kiszka <jan.kiszka@siemens.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*/

#include <jailhouse/control.h>
#include <jailhouse/processor.h>
#include <jailhouse/string.h>
#include <asm/efifb.h>

#define EFIFB_MAX_WIDTH 1920
#define EFIFB_MAX_HEIGHT 1080
#define EFIFB_FONT_WIDTH 8
#define EFIFB_FONT_HEIGHT 16
#define EFIFB_LINE_LEN (EFIFB_FONT_WIDTH * efifb_width)
#define EFIFB_FG_COLOR 0x00ff00 /* green */
#define EFIFB_BG_COLOR 0x000000 /* black */

asm(
" .pushsection \".rodata\"\n"
"font8x16:\n"
" .incbin \"altc-8x16\"\n"
" .popsection\n"
);

extern const u8 font8x16[];

static unsigned int efifb_width, efifb_height;
static char efifb_buffer[EFIFB_MAX_HEIGHT][EFIFB_MAX_WIDTH];
static u32 row_line;

static void efifb_write_char(unsigned int line, unsigned int row, char c)
{
unsigned int x, y, font_line, color, offs;

for (y = 0; y < EFIFB_FONT_HEIGHT; y++) {
font_line = font8x16[c * EFIFB_FONT_HEIGHT + y];

for (x = 0; x < EFIFB_FONT_WIDTH; x++) {
if (font_line & (1 << (EFIFB_FONT_WIDTH - x)))
color = EFIFB_FG_COLOR;
else
color = EFIFB_BG_COLOR;
offs = (row * EFIFB_FONT_WIDTH) + x +
(line * EFIFB_FONT_HEIGHT + y) * EFIFB_LINE_LEN;
((u32 *)hypervisor_header.debug_console_base)[offs] =
color;
}
}

efifb_buffer[line][row] = c;
}

static void efifb_scroll(void)
{
unsigned int row, line;

for (line = 0; line < (efifb_height - 1); line++)
for (row = 0; row < efifb_width; row++)
efifb_write_char(line, row,
efifb_buffer[line + 1][row]);

for (row = 0; row < efifb_width; row++)
efifb_write_char(efifb_height - 1, row, ' ');
}

void efifb_write(const char *msg)
{
/*
* panic_printk() avoids locking 'printk_lock' due to a potential
* deadlock in case a crash occurs while holding it. For avoiding
* a data race between printk and panic_printk, we take a local
* snapshot of both static variables and update them on return.
*/
u16 row = (u16)(row_line >> 16);
u16 line = (u16)row_line;

while (*msg != 0) {
if (panic_in_progress && panic_cpu != phys_processor_id())
return;

if (row == efifb_width || *msg == '\n') {
row = 0;
if (line == efifb_height - 1)
efifb_scroll();
else
line++;
}

if (*msg != '\n' && *msg != '\r') {
efifb_write_char(line, row, *msg);
row++;
}
msg++;
}

row_line = ((u32)row << 16) | (u32)line;
}

void efifb_init(void)
{
if (FB_IS_1920x1080(system_config->debug_console.flags)) {
efifb_width = 1920 / EFIFB_FONT_WIDTH;
efifb_height = 1080 / EFIFB_FONT_HEIGHT;
} else {
efifb_width = 1024 / EFIFB_FONT_WIDTH;
efifb_height = 876 / EFIFB_FONT_HEIGHT;
}
}
14 changes: 14 additions & 0 deletions hypervisor/arch/x86/include/asm/efifb.h
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Jailhouse, a Linux-based partitioning hypervisor
*
* Copyright (c) Siemens AG, 2018
*
* Authors:
* Jan Kiszka <jan.kiszka@siemens.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*/

void efifb_init(void);
void efifb_write(const char *msg);
9 changes: 8 additions & 1 deletion include/jailhouse/console.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#define JAILHOUSE_CON_TYPE_HSCIF 0x0006 #define JAILHOUSE_CON_TYPE_HSCIF 0x0006
#define JAILHOUSE_CON_TYPE_SCIFA 0x0007 #define JAILHOUSE_CON_TYPE_SCIFA 0x0007
#define JAILHOUSE_CON_TYPE_IMX 0x0008 #define JAILHOUSE_CON_TYPE_IMX 0x0008
#define JAILHOUSE_CON_TYPE_EFIFB 0x0009


/* Flags: bit 0 is used to select PIO (cleared) or MMIO (set) access */ /* Flags: bit 0 is used to select PIO (cleared) or MMIO (set) access */
#define JAILHOUSE_CON_ACCESS_PIO 0x0000 #define JAILHOUSE_CON_ACCESS_PIO 0x0000
Expand All @@ -65,7 +66,13 @@


#define CON_USES_REGDIST_1(flags) (((flags) & JAILHOUSE_CON_REGDIST_4) == 0) #define CON_USES_REGDIST_1(flags) (((flags) & JAILHOUSE_CON_REGDIST_4) == 0)


/* Bits 2-11: Reserved */ /* Flags: bit 2 is used to select framebuffer format */
#define JAILHOUSE_CON_FB_1024x768 0x0000
#define JAILHOUSE_CON_FB_1920x1080 0x0004

#define FB_IS_1920x1080(flags) !!((flags) & JAILHOUSE_CON_FB_1920x1080)

/* Bits 3-11: Reserved */


/* Bit 12 is used to indicate to clear instead of to set the clock gate */ /* Bit 12 is used to indicate to clear instead of to set the clock gate */
#define JAILHOUSE_CON_INVERTED_GATE 0x1000 #define JAILHOUSE_CON_INVERTED_GATE 0x1000
Expand Down

0 comments on commit 790ac72

Please sign in to comment.