Цветовая карта wsdisplay не получается правильно - PullRequest
0 голосов
/ 31 марта 2012

Я пытался использовать wscons и wsdisplay в NetBSD 5.1.2 (с использованием реализации кадрового буфера VESA) недавно, и я столкнулся с небольшим количеством проблема:

Я могу успешно установить цветовые карты, и они выглядят правильно, но получение цветовых карт, похоже, возвращает неверные данные , так что при попытке восстановить исходные карта цветов после завершения программы, все цвета неверны:

Vim, showing the program's source with a strange color map

Вот сокращенная программа, вызывающая проблему (обратите внимание, что она должна запускаться как root или как пользователь, вошедший во второй виртуальный терминал (/dev/ttyE1)):

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <dev/wscons/wsconsio.h>

int main(int argc, char **argv) {
    (void)argc, (void)argv;
    int tty = open("/dev/ttyE1", O_RDWR | O_EXCL);
    if(tty == -1) {
        perror("error opening tty");
        return EXIT_FAILURE;
    }
    struct wsdisplay_fbinfo fbinfo;
    if(ioctl(tty, WSDISPLAYIO_GINFO, &fbinfo) == -1) {
        perror("error retrieving framebuffer info");
        close(tty);
        return EXIT_FAILURE;
    }
    uint8_t *cmap_data = malloc(fbinfo.cmsize * 3);
    if(cmap_data == NULL) {
        perror("error allocating memory for color map data");
        close(tty);
        return EXIT_FAILURE;
    }
    struct wsdisplay_cmap cmap;
    cmap.index = 0;
    cmap.count = fbinfo.cmsize;
    cmap.red   = &cmap_data[fbinfo.cmsize * 0];
    cmap.green = &cmap_data[fbinfo.cmsize * 1];
    cmap.blue  = &cmap_data[fbinfo.cmsize * 2];
    if(ioctl(tty, WSDISPLAYIO_GETCMAP, &cmap) == -1) {
        perror("error getting color map");
        close(tty), free(cmap_data);
        return EXIT_FAILURE;
    }
    if(ioctl(tty, WSDISPLAYIO_PUTCMAP, &cmap) == -1) {
        perror("error putting color map");
        close(tty), free(cmap_data);
        return EXIT_FAILURE;
    }
    free(cmap_data);
    close(tty);
    return EXIT_SUCCESS;
}

Что я делаю не так и как я могу заставить его правильно получать и восстанавливать карты цветов?

1 Ответ

0 голосов
/ 01 апреля 2012

Причина

Я больше изучал проблему, и кажется, что некоторая память ядра либо неинициализирована, либо повреждена.В частности, sc_cmap_red, sc_cmap_green и sc_cmap_blue из struct vesafb_softcvesafbvar.h в строках 89–91) содержат неверные данные.Это несколько удивительно, поскольку строки с 719 по 722 из vesafb.c инициализируют его:

/* Fill in the softc colourmap arrays */
sc->sc_cmap_red[i / 3] = rasops_cmap[i + 0];
sc->sc_cmap_green[i / 3] = rasops_cmap[i + 1];
sc->sc_cmap_blue[i / 3] = rasops_cmap[i + 2];

Он содержит неверные данные, даже если я уберу это из оператора if, в котором он находитсяпоэтому он может быть поврежден, а не неинициализирован.

Драйвер способен правильно получать и устанавливать карты цветов;он просто не может получить исходную в struct vesafb_softc правильно.

Обходной путь

Простым решением было бы заставить программу переустановить цветовую карту по умолчанию.Как указывалось в приведенном выше фрагменте, было предположительно , чтобы получить начальные цвета от rasops_cmap, что определено в строках с 55 по 122 в rasops.c:

/* ANSI colormap (R,G,B). Upper 8 are high-intensity */
const u_char rasops_cmap[256*3] = {
    /* ... */
};

С помощью этих цветов вы можете создать программу, которая устанавливает их в качестве текущей карты цветов.Мне пришлось внести несколько изменений, чтобы курсор не исчезал, но он в основном работал.

Лучшее решение

Пока я искал дополнительную информацию, я нашел этосообщение в блоге .Когда я перекомпилировал ядро ​​с genfb(4) вместо vesafb(4), ядро ​​зависало при загрузке.Оказывается, это потому, что используемый мной загрузчик не был достаточно новым, чтобы передать ядру необходимые параметры.

Я случайно взглянул на NetBSD 6.0 changelog и заметил эту запись:

  • amd64 , i386
    Загрузчик был улучшен для поддержки консолей кадрового буфера с использованием расширений VESA BIOS.Эти изменения позволяют портам x86 работать с драйвером genfb (4) и отменяют драйвер только для i386 vesafb (4) . [jmcneill 20090216]

Я скачал NetBSD 6.0_BETA и загрузил его из приглашения загрузки следующим образом:

> vesa 640x480x8
> boot netbsd

... ивсе работало.

Короче говоря, использование более новой версии NetBSD и отключение vesafb(4) решают проблему.

...