Цветовая карта wsdisplay не получается правильно

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

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

Vim, показывая исходный код программы со странной цветовой картой

Вот сокращенная программа, вызывающая проблему (обратите внимание, что она должна быть запущена как 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 ответ

Решение

причина

Я больше разбирался в проблеме, и оказалось, что некоторая память ядра либо неинициализирована, либо повреждена. В частности, 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 и заметил эту запись:

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

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

> vesa 640x480x8
> boot netbsd

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

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

Другие вопросы по тегам