Hello,
Damien Zammit, le dim. 27 oct. 2024 09:38:01 +0000, a ecrit:
> When bootloader sets a linear framebuffer mode and passes
> the required info to Hurd via multiboot info table, we
> can use this framebuffer as is.
> Otherwise, fall back to EGA text mode as before.
Great :)
> +static void
> +blit_glyph(bdf_font_t font, char *mem, int ch, uint32_t rgb, int width, int
> bpp)
> +{
> + int w, h;
> +
> + struct bdf_glyph *gl;
> +
> + gl = bdf_find_glyph (font, ch, 0);
> + if (!gl)
> + gl = bdf_find_glyph (font, -1, ch);
> + if (!gl)
> + gl = bdf_find_glyph (font, '?', 0);
> +
> + assert_backtrace(gl != 0);
> +
> + for (h = 0; h < vga_hc; h++)
> + {
> + for (w = 0; w < vga_wc; w++)
> + {
> + char *pixel = mem + bpp/8 * (w + width * h);
> + uint32_t colour = (gl->bitmap[h] & (1 << (7-w))) ? rgb : 0;
You don't want to hardcode 0 as background, otherwise various
applications that use black on color will be unreadable.
You want to pass to such functions both fg_rgb and bg_rgb (as gotten from
attr.bgcol)
> + pixel[0] = (colour >> 16) & 0xff;
> + pixel[1] = (colour >> 8) & 0xff;
> + pixel[2] = colour & 0xff;
> + }
> + }
> +}
> +
> +static void
> +blit_glyph_xor(bdf_font_t font, char *mem, int ch, uint32_t rgb, int width,
> int bpp)
> +{
> + int w, h;
> +
> + struct bdf_glyph *gl;
> + gl = bdf_find_glyph (font, ch, 0);
> + if (!gl)
> + gl = bdf_find_glyph (font, -1, ch);
> + if (!gl)
> + gl = bdf_find_glyph (font, '?', 0);
Rather create a function that looks for these alternatives, that we'll
be able to use in all the existing places that are already trying -1 as
alternative (and could then be using '?' as well like you did).
> + assert_backtrace(gl != 0);
That function could return a hardcoded fallback, see
console-client/vga-dynafont.c:594
> + for (h = 0; h < vga_hc; h++)
> + {
> + for (w = 0; w < vga_wc; w++)
> + {
> + char *pixel = mem + bpp/8 * (w + width * h);
> + uint32_t colour = (gl->bitmap[h] & (1 << (7-w))) ? rgb : 0;
> + pixel[0] ^= (colour >> 16) & 0xff;
> + pixel[1] ^= (colour >> 8) & 0xff;
> + pixel[2] ^= colour & 0xff;
> + }
> + }
> +}
> +
> +static error_t
> +fb_init(void)
> +{
> + error_t err;
> + int fd;
> +
> + fd = open ("/dev/mem", O_RDWR);
> + if (fd >= 0)
Better invert that test, that'll avoid the indentation.
> + {
> + vga_videomem = mmap (0, vga_width * vga_height * vga_bpp/8, PROT_READ
> | PROT_WRITE,
> + MAP_SHARED, fd, vga_fb);
> + err = errno;
> + close (fd);
> + if (vga_videomem == (void *) -1)
Rather use MMAP_FAILED.
> + return err;
> + }
> + else
> + return errno;
> +
> + /* Clear screen */
> + memset (vga_videomem, 0, vga_width * vga_height * vga_bpp/8);
> + return 0;
> +}
[...]
> +/* First 8 colours of EGA palette */
> +uint32_t console_rgb[8] = {
> + 0x000000, /* black */
> + 0x0000aa, /* blue */
> + 0x00aa00, /* green */
> + 0x00aaaa, /* cyan */
> + 0xaa0000, /* red */
> + 0xaa00aa, /* magenta */
> + 0xffff55, /* yellow */
That's rather aa5500.
> + 0xaaaaaa /* white */
> +};
Also, we don't want to use the EGA palette, but the ANSI palette:
\x1b[30m foreground black
\x1b[31m foreground red
\x1b[32m foreground green
\x1b[33m foreground yellow
\x1b[34m foreground blue
\x1b[35m foreground magenta
\x1b[36m foreground cyan
\x1b[37m foreground white
otherwise the colors will be wrong.
And while at it, you can hardcode the 8 bright colors:
0x555555 bright black
0xff5555 bright red
0x55ff55 bright green
0xffff55 bright yellow
0x5555ff bright blue
0xff55ff bright magenta
0x55ffff bright cyan
0xffffff bright white
to be used when attr.intensity == CONS_ATTR_INTENSITY_BOLD
> +static void
> +hide_mousecursor (struct fb_display *disp)
> +{
> + char *oldpos = vga_videomem + vga_bpp/8 * ((int) disp->mousecursor.posy *
> vga_hc * disp->width
> + + (int) disp->mousecursor.posx * vga_wc);
Make this computation a macro, you have a lot of such.
> + if (!disp->mousecursor.visible)
> + return;
> +
> + /* First remove the old cursor. */
> + blit_glyph_xor (disp->font, oldpos, 'X', 0x00ff00, disp->width, vga_bpp);
> + disp->mousecursor.visible = 0;
> +}
> +static void
> +hide_cursor(struct fb_display *disp)
> +{
> + int x, y;
> + char *curpos;
> +
> + if (cursor_hidden)
> + return;
> +
> + /* Remove old cursor */
> + x = cursor_pos % (disp->width/vga_wc);
> + y = cursor_pos / (disp->width/vga_wc);
> + curpos = vga_videomem + vga_bpp/8 * (y * vga_hc * disp->width + x *
> vga_wc);
> + blit_glyph_xor (disp->font, curpos, '_', 0xffffff, disp->width, vga_bpp);
> + cursor_hidden = 1;
> +}
Rather use 0x2581, otherwise the cursor will be invisible over '_'.
> +/* Set the cursor's position on display HANDLE to column COL and row
> + ROW. */
> +static error_t
> +fb_display_set_cursor_pos (void *handle, uint32_t col, uint32_t row)
> +{
> + struct fb_display *disp = handle;
> +
> + /* If the cursor did not move from the character position, don't
> + bother about updating the cursor position. */
> + if (cursor_state && (col == (cursor_pos % (disp->width/vga_wc)))
> + && (row == (cursor_pos / (disp->width/vga_wc))))
> + return 0;
> +
> + hide_cursor (disp);
Since hide_cursor will xor, we'd want an if (cursor_state) here too.
> + cursor_pos = col + disp->width/vga_wc * row;
It doesn't seem useful to keep cursor_pos as just one number? Better
have cursor_pos_x and _y.
> + if (cursor_state)
> + draw_cursor (disp);
> +
> + return 0;
> +}
> +
> +/* Deallocate any scarce resources occupied by the LENGTH characters
> + from column COL and row ROW. */
You don't have anything to do here. See the clear field comment:
«
If there are no scarce resources, the caller might do nothing.
»
> +static error_t
> +fb_display_clear (void *handle, size_t length, uint32_t col, uint32_t row)
> +{
> + int len;
> + struct fb_display *disp = handle;
> + struct fbchr *refpos = &disp->refmatrix[row][0];
> + char *pos = vga_videomem;
> +
> +/* Scroll the display by the desired number of lines. The area that becomes
> + free will be filled in a subsequent write call. */
> +static error_t
> +fb_display_scroll (void *handle, int delta)
> +{
> + struct fb_display *disp = handle;
> + int pixels, chars, nextdelta = 0;
> + char *pos = vga_videomem;
> + uint32_t r;
> +
> + if (delta > disp->height/vga_hc)
> + {
> + nextdelta = delta - disp->height/vga_hc;
> + delta = disp->height/vga_hc;
> + }
> + else if (delta < -(disp->height/vga_hc))
> + {
> + nextdelta = delta + disp->height/vga_hc;
> + delta = -(disp->height/vga_hc);
> + }
There is no use trying to wrap around like this: if delta is larger than
the height, we just don't copy anything, and the caller will actually
write the whole screen. See the comment of the scroll field.
> + pixels = abs(delta)*vga_hc * disp->width;
> + chars = abs(delta) * disp->width/vga_wc;
> +
> + hide_mousecursor (disp);
> + hide_cursor (disp);
> +
> + /* XXX: If the virtual console is bigger than the physical console it is
> + impossible to scroll because the data to scroll is not in memory. */
> + if (current_height > disp->height/vga_hc)
> + return ENOTSUP;
> +
> + if (delta > 0)
> + {
> + memmove (vga_videomem, vga_videomem + vga_bpp/8 * pixels,
> + vga_bpp/8 * disp->width * (disp->height - delta*vga_hc));
> + }
> + else
> + {
> + memmove (vga_videomem + vga_bpp/8 * pixels, vga_videomem,
> + vga_bpp/8 * disp->width * (disp->height + delta*vga_hc));
> + }
> +
> + if (delta > 0)
> + {
> + r = disp->height/vga_hc - delta;
> + memmove (&disp->refmatrix[0][0], &disp->refmatrix[0][0] + chars,
> + sizeof (struct fbchr) * disp->width/vga_wc * r);
> + pos += vga_bpp/8 * (r*vga_hc * disp->width);
> + }
> + else
> + {
> + r = 0;
> + memmove (&disp->refmatrix[0][0] + chars, &disp->refmatrix[0][0],
> + sizeof (struct fbchr) * disp->width/vga_wc *
> (disp->height/vga_hc + delta));
> + }
> +
> + fb_display_clear (disp, chars, 0, r);
We don't need to clear, we have nothing there to do.
> + if (nextdelta)
> + fb_display_scroll (handle, nextdelta);
> +
> + return 0;
> +}
> +
> +
> +
> +/* Write the text STR with LENGTH characters to column COL and row
> + ROW. */
> +static error_t
> +fb_display_write (void *handle, conchar_t *str, size_t length,
> + uint32_t col, uint32_t row)
> +{
> + struct fb_display *disp = handle;
> + char *pos;
> + struct fbchr *refpos = &disp->refmatrix[row][col];
> + char *mouse_cursor_pos;
> +
> + hide_mousecursor (disp);
> + hide_cursor (disp);
> +
> + /* The starting column is outside the physical screen. */
> + if (disp->width/vga_wc < current_width && col >= disp->width/vga_wc)
> + {
> + size_t skip = current_width - disp->width/vga_wc;
> + str += skip;
> + length -= skip;
> + col = 0;
> + row += skip / current_width + 1;
Why skip/current_width? By construction, skip < current_width. We only
ever go to the next line, we have no reason to skip several lines.
> + }
> +
> + mouse_cursor_pos = vga_videomem + vga_bpp/8
> + * ((int) disp->mousecursor.posy*vga_hc
> + * disp->width + (int) disp->mousecursor.posx*vga_wc);
> +
> + while (length--)
> + {
> + int charval = str->chr;
You changed the col++ position. Better do the same in the vga driver, to
avoid divergence between both.
> + /* The virtual console is smaller than the physical screen. */
> + if (col >= current_width)
> + {
> + size_t skip = disp->width/vga_wc - current_width;
> + refpos += skip;
> + col = 0;
> + row += skip / disp->width/vga_wc + 1;
ditto
> + }
> + /* The virtual console is bigger than the physical console. */
> + else if (disp->width/vga_wc < current_width && col ==
> disp->width/vga_wc)
> + {
> + size_t skip = current_width - disp->width/vga_wc;
> + str += skip;
> + length -= skip;
> + col = skip % current_width;
> + row += skip / current_width;
ditto
> + }
> +
> + /* The screen is filled until the bottom of the screen. */
> + if (row >= disp->height/vga_hc)
Why /vga_hc??
> + return 0;
> +
> + pos = vga_videomem + (col*vga_wc + (row*vga_hc * disp->width)) *
> vga_bpp/8;
> +
> + /* blit glyph to screen */
> + blit_glyph(disp->font, pos, charval, console_rgb[str->attr.fgcol],
> disp->width, vga_bpp);
> +
> + if (pos == mouse_cursor_pos)
> + disp->mousecursor.visible = 0;
> +
> + /* Perform reference counting. */
That comment was for code that you removed.
> + refpos->used = 1;
> + refpos->chr = charval;
> + refpos->fgcol = str->attr.fgcol;
> + refpos++;
> + col++;
> +
> + /* Go to next character. */
> + str++;
> + }
> + return 0;
> +}
> +
> +static error_t
> +fb_set_mousecursor_pos (void *handle, float x, float y)
> +{
> + struct fb_display *disp = handle;
> +
> + /* If the mouse did not move from the character position, don't
> + bother about updating the cursor position. */
> + if (disp->mousecursor.visible && x == (int) disp->mousecursor.posx
> + && y == (int) disp->mousecursor.posy)
> + return 0;
> +
> + hide_mousecursor (disp);
Since hide_mousecursor will xor, we'd want an if (cursor_state) here too.
> + disp->mousecursor.posx = x;
> + disp->mousecursor.posy = y;
> +
> + if (disp->mousecursor.enabled)
> + draw_mousecursor (disp);
> +
> + return 0;
> +}
> +
> +
> diff --git a/console-client/fb.h b/console-client/fb.h
> new file mode 100644
> index 00000000..23e0a51a
> --- /dev/null
> +++ b/console-client/fb.h
> @@ -0,0 +1,74 @@
> +struct fbchr
> +{
> + unsigned int used : 1;
> + unsigned int chr : 9;
You want a whole wchar_t, we don't have the 512-glyph limitation
> + unsigned int fgcol: 3;
> +};
> +
> +typedef struct fb_mousecursor
> +{
> + float posx;
> + float posy;
> + int visible;
> + int enabled;
> +} fb_mousecursor_t;
> +
> +struct fb_display
> +{
> + /* The font for this display. */
> + bdf_font_t font;
> +
> + int df_size;
> + int df_width;
> +
> + /* The color palette. */
> + dynacolor_t dc;
This is unused (no hardware palette)
> + int width;
> + int height;
> +
> + /* The state of the mouse cursor. */
> + fb_mousecursor_t mousecursor;
> +
> + /* The position of the cursor, x_pos + y_pos * width (in characters) */
> + int cursor_pos;
> +
> + /* Remember for each cell on the display the glyph written to it and
> + the colours assigned. 0 means unassigned. */
> +
> + struct fbchr refmatrix[VGA_VIDEO_MEM_MAX_H /
> VGA_PIXELS_H][VGA_VIDEO_MEM_MAX_W / VGA_PIXELS_W];
> +};
> +
> +#endif
> diff --git a/console-client/vga-hw.h b/console-client/vga-hw.h
> index b4212e62..71ffb721 100644
> --- a/console-client/vga-hw.h
> +++ b/console-client/vga-hw.h
> @@ -24,6 +24,13 @@
> #define VGA_VIDEO_MEM_BASE_ADDR 0x0b8000
> #define VGA_VIDEO_MEM_LENGTH 0x004000
>
> +#define VGA_VIDEO_MEM_MAX_W 1920
> +#define VGA_VIDEO_MEM_MAX_H 1080
> +#define VGA_VIDEO_MEM_MAX_BPP 32
> +
> +#define VGA_PIXELS_W 8
> +#define VGA_PIXELS_H 16
This is not related to hardware conditions, better put them fb.h.
> #define VGA_FONT_BUFFER 8
> #define VGA_FONT_SIZE 256
> #define VGA_FONT_HEIGHT 32
> diff --git a/console-client/vga-support.c b/console-client/vga-support.c
> index 32ede46d..0fa229d4 100644
> --- a/console-client/vga-support.c
> +++ b/console-client/vga-support.c
> @@ -25,6 +25,9 @@
> #include <sys/io.h>
> #include <sys/mman.h>
> #include <sys/types.h>
> +#include <device/device.h>
> +#include <hurd.h>
> +#include <mach.h>
> #include <string.h>
> #include <stdlib.h>
>
> @@ -32,8 +35,15 @@
> #include "vga-support.h"
>
>
> -/* The base of the video memory mapping. */
> +/* The parameters of the video memory mapping. */
> char *vga_videomem;
> +size_t vga_fb;
That should rather be an off_t
> +int vga_pitch;
> +int vga_width;
> +int vga_height;
> +int vga_bpp;
> +int vga_wc;
> +int vga_hc;
>
> /* The saved state of the VGA card. */
> struct vga_state
> @@ -56,14 +66,65 @@ struct vga_state
> unsigned char attr_mode;
>
> /* Alignment is required by some "hardware", and optimizes transfers. */
> - char videomem[2 * 80 * 25]
> + char videomem[VGA_VIDEO_MEM_MAX_W * VGA_VIDEO_MEM_MAX_H *
> VGA_VIDEO_MEM_MAX_BPP / 8]
? No need to tinker with the vga driver videomem, and it's text cells
there, not pixels.
> __attribute__ ((aligned (__BIGGEST_ALIGNMENT__)));
> - unsigned char fontmem[2 * VGA_FONT_SIZE * VGA_FONT_HEIGHT]
> + unsigned char fontmem[VGA_VIDEO_MEM_MAX_BPP / 8 * VGA_FONT_SIZE *
> VGA_FONT_HEIGHT]
> __attribute__ ((aligned (__BIGGEST_ALIGNMENT__)));
Even more so: VGA fonts is really always 2*256 glyphs.
> };
>
> static struct vga_state *vga_state;
>
> +error_t
> +vga_get_multiboot_params (void)
> +{
> + error_t ret = 0;
> + mach_port_t master_device, mbinfo_dev;
> + struct multiboot_raw_info mbi;
> + char buf[sizeof(struct multiboot_raw_info)] = {0};
? No need to initialize the array.
> + char *bufptr = &buf[0];
> + uint32_t bytes = sizeof(struct multiboot_raw_info);
> + uint32_t bytes_read = 0;
> +
> + ret = get_privileged_ports (NULL, &master_device);
> + if (ret)
> + goto fail;
> +
> + ret = device_open (master_device, D_READ, "mbinfo", &mbinfo_dev);
> + mach_port_deallocate (mach_task_self (), master_device);
> + if (ret)
> + goto fail;
> +
> + ret = device_read (mbinfo_dev, D_READ, 0, bytes, &bufptr, &bytes_read);
> + mach_port_deallocate (mach_task_self (), mbinfo_dev);
> + if (ret)
> + goto fail;
> +
> + if (bytes_read != bytes)
> + goto fail;
> +
> + memcpy((void *)&mbi, (void *)bufptr, sizeof(struct multiboot_raw_info));
> +
> + vga_fb = mbi.fb_info.framebuffer_addr;
> + vga_pitch = mbi.fb_info.framebuffer_pitch;
> + vga_width = mbi.fb_info.framebuffer_width;
> + vga_height = mbi.fb_info.framebuffer_height;
> + vga_bpp = mbi.fb_info.framebuffer_bpp;
> + vga_wc = VGA_PIXELS_W;
> + vga_hc = VGA_PIXELS_H;
These two should be taken from the font. The bdf format unfortunately
doesn't really provide the information (glyphs 0-31 are 16x16 in
vga-system.bdf for instance). As a workaround you can take the bbox of
the glyph for U+0020.
> + return ret;
> +
> +fail:
> + /* Fall back to EGA text mode */
> + vga_fb = VGA_VIDEO_MEM_BASE_ADDR;
> + vga_pitch = 160;
> + vga_width = 80;
> + vga_height = 25;
> + vga_bpp = 16;
> + vga_wc = 1;
> + vga_hc = 1;
I don't think you need to initialize anything, provided you do not change
the vga driver. And you can then call these fb_*, that'll mean something
for non-vga hardware.
> + return ret;
> +}
> +
>
> error_t
> vga_init (void)
> @@ -87,8 +148,8 @@ vga_init (void)
> fd = open ("/dev/mem", O_RDWR);
> if (fd >= 0)
> {
> - vga_videomem = mmap (0, VGA_VIDEO_MEM_LENGTH, PROT_READ | PROT_WRITE,
> - MAP_SHARED, fd, VGA_VIDEO_MEM_BASE_ADDR);
> + vga_videomem = mmap (0, vga_width * vga_height * vga_bpp, PROT_READ |
> PROT_WRITE,
> + MAP_SHARED, fd, vga_fb);
In vga, bpp is always 2, and the video memory is always
VGA_VIDEO_MEM_LENGTH (which allows to have some scrollback history
actually). I don't think it's useful to mess with the vga driver, this
is unrelated work.
> err = errno;
> close (fd);
> if (vga_videomem == (void *) -1)
> @@ -147,13 +208,13 @@ vga_init (void)
> outb (VGA_GFX_MODE_ADDR, VGA_GFX_ADDR_REG);
> outb (VGA_GFX_MODE_HOSTOE, VGA_GFX_DATA_REG);
>
> - memcpy (vga_state->videomem, vga_videomem, 2 * 80 * 25);
> + memcpy (vga_state->videomem, vga_videomem, vga_width * vga_height *
> vga_bpp / 8);
> vga_read_font_buffer (0, 0, vga_state->fontmem,
> - 2 * VGA_FONT_SIZE * VGA_FONT_HEIGHT);
> + vga_bpp/8 * VGA_FONT_SIZE * VGA_FONT_HEIGHT);
>
> - /* 80 cols, 25 rows, two bytes per cell and twice because with lower
> + /* X cols, Y rows, bpp/8 bytes per cell and twice because with lower
> max scan line we get more lines on the screen. */
> - memset (vga_videomem, 0, 80 * 25 * 2 * 2);
> + memset (vga_videomem, 0, vga_width * vga_height * vga_bpp / 4);
>
> return 0;
> }
> @@ -166,8 +227,8 @@ vga_fini (void)
> {
> /* Recover the saved state. */
> vga_write_font_buffer (0, 0, vga_state->fontmem,
> - 2 * VGA_FONT_SIZE * VGA_FONT_HEIGHT);
> - memcpy (vga_videomem, vga_state->videomem, 2 * 80 * 25);
> + vga_bpp/8 * VGA_FONT_SIZE * VGA_FONT_HEIGHT);
> + memcpy (vga_videomem, vga_state->videomem, vga_width * vga_height *
> vga_bpp / 8);
>
> /* Restore the registers. */
> outb (VGA_SEQ_CLOCK_MODE_ADDR, VGA_SEQ_ADDR_REG);
> @@ -207,7 +268,7 @@ vga_fini (void)
> outb (0x00, VGA_ATTR_ADDR_DATA_REG);
>
> ioperm (VGA_MIN_REG, VGA_MAX_REG - VGA_MIN_REG + 1, 0);
> - munmap (vga_videomem, VGA_VIDEO_MEM_LENGTH);
> + munmap (vga_videomem, vga_width * vga_height * vga_bpp);
> }
>
>
> @@ -225,7 +286,7 @@ vga_read_write_font_buffer (int write, int buffer, int
> index,
> char saved_gfx_misc;
>
> int offset = buffer * VGA_FONT_SIZE + index * VGA_FONT_HEIGHT;
> - assert_backtrace (offset >= 0 && offset + datalen <= VGA_VIDEO_MEM_LENGTH);
> + assert_backtrace (offset >= 0 && offset + datalen <= vga_width *
> vga_height * vga_bpp);
>
> /* Select plane 2 for sequential writing. You might think it is not
> necessary for reading, but it is. Likewise for read settings
> diff --git a/console-client/vga-support.h b/console-client/vga-support.h
> index 17c0b5fd..a3de5aea 100644
> --- a/console-client/vga-support.h
> +++ b/console-client/vga-support.h
> @@ -23,6 +23,57 @@
>
> #include <errno.h>
> #include <sys/types.h>
> +#include <stdint.h>
> +
> +struct multiboot_framebuffer_info {
> + uint64_t framebuffer_addr;
> + uint32_t framebuffer_pitch;
> + uint32_t framebuffer_width;
> + uint32_t framebuffer_height;
> + uint8_t framebuffer_bpp;
> +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
> +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
> +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
> + uint8_t framebuffer_type;
> + union
> + {
> + struct
> + {
> + uint32_t framebuffer_palette_addr;
> + uint16_t framebuffer_palette_num_colors;
> + };
> + struct
> + {
> + uint8_t framebuffer_red_field_position;
> + uint8_t framebuffer_red_mask_size;
> + uint8_t framebuffer_green_field_position;
> + uint8_t framebuffer_green_mask_size;
> + uint8_t framebuffer_blue_field_position;
> + uint8_t framebuffer_blue_mask_size;
> + };
> + };
> +} __attribute__((packed));
> +
> +/*
> + * Multiboot information structure as passed by the boot loader.
> + */
> +struct multiboot_raw_info {
> + uint32_t flags;
> + uint32_t mem_lower;
> + uint32_t mem_upper;
> + uint32_t unused0;
> + uint32_t cmdline;
> + uint32_t mods_count;
> + uint32_t mods_addr;
> + uint32_t shdr_num;
> + uint32_t shdr_size;
> + uint32_t shdr_addr;
> + uint32_t shdr_strndx;
> + uint32_t mmap_length;
> + uint32_t mmap_addr;
> + uint32_t unused1[9];
> + struct multiboot_framebuffer_info fb_info;
> +} __attribute__((packed));
Rather put them in a separate header, it's unrelated to vga.
> @@ -32,6 +83,15 @@
>
> /* The mapped video memory. */
> extern char *vga_videomem;
> +extern size_t vga_fb;
> +extern int vga_width;
> +extern int vga_height;
> +extern int vga_bpp;
> +extern int vga_wc;
> +extern int vga_hc;
> +
> +/* Get the multiboot video parameters */
> +error_t vga_get_multiboot_params (void);
>
> /* Initialize the VGA hardware and set up the permissions and memory
> mappings. */
> diff --git a/console-client/vga.c b/console-client/vga.c
> index e954013d..67e7e3f2 100644
> --- a/console-client/vga.c
> +++ b/console-client/vga.c
> @@ -37,6 +37,7 @@
> #include "driver.h"
> #include "timer.h"
>
> +#include "fb.h"
> #include "vga-hw.h"
> #include "vga-support.h"
> #include "bdf.h"
> @@ -45,8 +46,6 @@
> #include "unicode.h"
>
>
> -#define VGA_DISP_WIDTH 80
> -#define VGA_DISP_HEIGHT 25
>
> /* The font file. */
> #define DEFAULT_VGA_FONT DEFAULT_VGA_FONT_DIR "vga-system.bdf"
> @@ -87,15 +86,19 @@ static int cursor_state;
> /* Is set to 1 if the cursor moved out of the physical screen and the
> cursor state should be hidden. */
> static int cursor_hidden;
> +
> +/* Forward declaration */
> +struct driver_ops driver_vga_ops;
> +
>
> +
> struct refchr
> {
> unsigned int used : 1;
> unsigned int chr : 9;
> - unsigned int attr : 8;
> + unsigned int attr: 8;
Avoid unrelated changes.
> };
>
> -
> typedef struct vga_mousecursor
> {
> float posx;
> @@ -129,7 +132,7 @@ struct vga_display
> /* Remember for each cell on the display the glyph written to it and
> the colors (in the upper byte) assigned. 0 means unassigned. */
>
> - struct refchr refmatrix[VGA_DISP_HEIGHT][VGA_DISP_WIDTH];
> + struct refchr refmatrix[VGA_VIDEO_MEM_MAX_H /
> VGA_PIXELS_H][VGA_VIDEO_MEM_MAX_W / VGA_PIXELS_W];
You don't need to change this, the vga driver is really stuck with
hardware vga constraints, which are completely beneath fb capabilities.
> };
>
>
> @@ -279,9 +282,12 @@ vga_display_init (void **handle, int no_exit, int argc,
> char *argv[],
> int *next)
> {
> error_t err;
> - struct vga_display *disp;
> + struct vga_display *vgadisp;
> + struct fb_display *fbdisp;
> int pos = 1;
>
> + vga_get_multiboot_params();
> +
> /* XXX Assert that we are called only once. */
> pthread_mutex_init (&vga_display_lock, NULL);
> timer_clear (&vga_display_timer);
> @@ -294,22 +300,43 @@ vga_display_init (void **handle, int no_exit, int argc,
> char *argv[],
> if (err && err != EINVAL)
> return err;
>
> - /* Create and initialize the display structure as much as
> - possible. */
> - disp = calloc (1, sizeof *disp);
> - if (!disp)
> - return ENOMEM;
> + if (vga_fb == VGA_VIDEO_MEM_BASE_ADDR)
Should we not rather use
framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT?
in theory a framebuffer could be at VGA_VIDEO_MEM_BASE_ADDR
> + {
> + /* EGA text mode */
> + vgadisp = calloc (1, sizeof *vgadisp);
> + if (!vgadisp)
> + return ENOMEM;
> +
> + vgadisp->df_size = vga_display_max_glyphs ? 512 : 256;
> + vgadisp->df_width = vga_display_font_width;
> + vgadisp->width = vga_width;
> + vgadisp->height = vga_height;
>
> - disp->df_size = vga_display_max_glyphs ? 512 : 256;
> - disp->df_width = vga_display_font_width;
> - disp->width = VGA_DISP_WIDTH;
> - disp->height = VGA_DISP_HEIGHT;
> + *handle = vgadisp;
> + }
> + else
> + {
> + /* Linear framebuffer! */
> + fbdisp = calloc (1, sizeof *fbdisp);
> + if (!fbdisp)
> + return ENOMEM;
> +
> + fbdisp->df_size = vga_display_max_glyphs ? 512 : 256;
> + fbdisp->df_width = vga_display_font_width;
> + fbdisp->width = vga_width;
> + fbdisp->height = vga_height;
> +
> + /* dynamically switch drivers */
> + driver_vga_ops.start = fb_display_start;
> + driver_vga_ops.fini = fb_display_fini;
> + driver_vga_ops.restore_status = NULL;
> +
> + *handle = fbdisp;
> + }
>
> - *handle = disp;
> return 0;
> }
>
> -
> /* Start the driver. */
> static error_t
> vga_display_start (void *handle)
> --
> 2.45.2
>
>
>