vt(4): add support for configurable console palette

Introduce new set of loader tunables kern.vt.color.N.rgb, where N is a
number from 0 to 15. The value is either comma-separated list decimal
numbers ranging from 0 to 255 that represent values of red, green, and
blue components respectively (i.e. "128,128,128") or 6-digit hex triplet
commonly used to represent colors in HTML or xterm settings (i.e. #808080)

Each tunable overrides one of the 16 hardcoded palette codes and can be set
in loader.conf(5)

Reviewed by:	bcr(docs), jilles, manu, ray
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D13645
This commit is contained in:
Oleksandr Tymoshenko 2017-12-31 20:21:05 +00:00
parent 4e05ac247c
commit 29f61a2f42
2 changed files with 118 additions and 5 deletions

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd July 19, 2016
.Dd December 28, 2017
.Dt "VT" 4
.Os
.Sh NAME
@ -45,6 +45,7 @@ In
.Xr loader.conf 5 :
.Cd hw.vga.textmode=1
.Cd kern.vty=vt
.Cd kern.vt.color.<colornum>.rgb="<colorspec>"
.Cd kern.vt.fb.default_mode="<X>x<Y>"
.Cd kern.vt.fb.modes.<connector>="<X>x<Y>"
.Pp
@ -206,6 +207,16 @@ The
kernel uses
.Nm
when this value is not set.
.It Va kern.vt.color. Ns Ar colornum Ns Va .rgb
Set this value to override default palette entry for color
.Pa colornum
which should be in a range from 0 to 15 inclusive.
The value should be either a comma-separated triplet of
red, green, and blue values in a range from 0 to 255 or
HTML-like hex triplet.
See
.Sx EXAMPLES
below.
.It Va kern.vt.fb.default_mode
Set this value to a graphic mode to override the default mode picked by the
.Nm
@ -310,6 +321,11 @@ The connector name was found in
.Dl info: [drm] Connector LVDS-1: get mode from tunables:
.Dl info: [drm] - kern.vt.fb.modes.LVDS-1
.Dl info: [drm] - kern.vt.fb.default_mode
.Pp
To set black and white colors of console palette
.Pp
.Dl kern.vt.color.0.rgb="10,10,10"
.Dl kern.vt.color.15.rgb="#f0f0f0"
.Sh SEE ALSO
.Xr kbdcontrol 1 ,
.Xr login 1 ,

View File

@ -33,14 +33,18 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/libkern.h>
#include <dev/vt/colors/vt_termcolors.h>
static const struct {
#define NCOLORS 16
static struct {
unsigned char r; /* Red percentage value. */
unsigned char g; /* Green percentage value. */
unsigned char b; /* Blue percentage value. */
} color_def[16] = {
} color_def[NCOLORS] = {
{0, 0, 0}, /* black */
{50, 0, 0}, /* dark red */
{0, 50, 0}, /* dark green */
@ -65,19 +69,112 @@ static const struct {
* - blue and red are swapped (1 <-> 4)
* - yellow ad cyan are swapped (3 <-> 6)
*/
static const int cons_to_vga_colors[16] = {
static const int cons_to_vga_colors[NCOLORS] = {
0, 4, 2, 6, 1, 5, 3, 7,
0, 4, 2, 6, 1, 5, 3, 7
};
static int
vt_parse_rgb_triplet(const char *rgb, unsigned char *r,
unsigned char *g, unsigned char *b)
{
unsigned long v;
const char *ptr;
char *endptr;
ptr = rgb;
/* Handle #rrggbb case */
if (*ptr == '#') {
if (strlen(ptr) != 7)
return (-1);
v = strtoul(ptr + 1, &endptr, 16);
if (*endptr != '\0')
return (-1);
*r = (v >> 16) & 0xff;
*g = (v >> 8) & 0xff;
*b = v & 0xff;
return (0);
}
/* "r, g, b" case */
v = strtoul(ptr, &endptr, 10);
if (ptr == endptr)
return (-1);
if (v > 255)
return (-1);
*r = v & 0xff;
ptr = endptr;
/* skip separator */
while (*ptr == ',' || *ptr == ' ')
ptr++;
v = strtoul(ptr, &endptr, 10);
if (ptr == endptr)
return (-1);
if (v > 255)
return (-1);
*g = v & 0xff;
ptr = endptr;
/* skip separator */
while (*ptr == ',' || *ptr == ' ')
ptr++;
v = strtoul(ptr, &endptr, 10);
if (ptr == endptr)
return (-1);
if (v > 255)
return (-1);
*b = v & 0xff;
ptr = endptr;
/* skip trailing spaces */
while (*ptr == ' ')
ptr++;
/* unexpected characters at the end of the string */
if (*ptr != 0)
return (-1);
return (0);
}
static void
vt_palette_init()
{
int i;
char rgb[32];
char tunable[32];
unsigned char r, g, b;
for (i = 0; i < NCOLORS; i++) {
snprintf(tunable, sizeof(tunable),
"kern.vt.color.%d.rgb", i);
if (TUNABLE_STR_FETCH(tunable, rgb, sizeof(rgb))) {
if (vt_parse_rgb_triplet(rgb, strlen(rgb), &r, &g, &b) == 0) {
/* convert to percentages */
color_def[i].r = r*100/255;
color_def[i].g = g*100/255;
color_def[i].b = b*100/255;
}
}
}
}
int
vt_generate_cons_palette(uint32_t *palette, int format, uint32_t rmax,
int roffset, uint32_t gmax, int goffset, uint32_t bmax, int boffset)
{
int i;
vt_palette_init();
#define CF(_f, _i) ((_f ## max * color_def[(_i)]._f / 100) << _f ## offset)
for (i = 0; i < 16; i++) {
for (i = 0; i < NCOLORS; i++) {
switch (format) {
case COLOR_FORMAT_VGA:
palette[i] = cons_to_vga_colors[i];