Bare metal VGA: pass video mode information via struct mman

This should hopefully help us adapt the VGA console code, to
work with video modes other than 80 × 25 × 16 text.
This commit is contained in:
tkchia 2022-09-22 22:26:54 +00:00
parent 8089876c51
commit 388c4f6060
5 changed files with 43 additions and 24 deletions

View file

@ -163,6 +163,12 @@ noasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t) {
export_offsetof(struct mman, e820);
export_offsetof(struct mman, e820_end);
export_offsetof(struct mman, bad_idt);
export_offsetof(struct mman, pc_video_type);
export_offsetof(struct mman, pc_video_stride);
export_offsetof(struct mman, pc_video_width);
export_offsetof(struct mman, pc_video_height);
export_offsetof(struct mman, pc_video_framebuffer);
export_offsetof(struct mman, pc_video_framebuffer_size);
__normalize_e820(mm);
__invert_memory(mm, pml4t);
}

View file

@ -18,8 +18,26 @@ struct mman {
unsigned char pc_drive_last_head; /* 0x1d21 */
unsigned char pc_drive; /* 0x1d22 */
char bad_idt[6]; /* 0x1d23 */
unsigned char pc_video_type; /* 0x1d29 */
unsigned short pc_video_stride; /* 0x1d2a — line width, including any
invisible "pixels" in
bytes (NOTE) */
unsigned short pc_video_width; /* 0x1d2c — width in chars. (text)
or pixels (graphics) */
unsigned short pc_video_height; /* 0x1d2e — height in chars. (text)
or pixels (graphics) */
uint32_t pc_video_framebuffer; /* 0x1d30 */
uint32_t pc_video_framebuffer_size; /* 0x1d34 */
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
/* Values for mman::pc_video_type. TODO: implement graphics modes. */
#define PC_VIDEO_TEXT 0
#define PC_VIDEO_BGR565 1
#define PC_VIDEO_BGR555 2
#define PC_VIDEO_BGRX8888 3
#define PC_VIDEO_RGBX8888 4
#endif /* COSMOPOLITAN_LIBC_RUNTIME_MMAN_H_ */

View file

@ -25,6 +25,7 @@
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/macros.internal.h"
#include "libc/runtime/mman.internal.h"
#include "libc/vga/vga.internal.h"
// Code snippet for initializing the VGA video mode for bare metal.
@ -58,6 +59,13 @@
mov $0x0500,%ax # just make sure we are on display
# page 0
2: int $0x10 # otherwise, change the video mode
.set mm,0x0500 # note down video mode parameters
movb $PC_VIDEO_TEXT,mm+"struct mman::pc_video_type"
movw $160,mm+"struct mman::pc_video_stride"
movw $80,mm+"struct mman::pc_video_width"
movw $25,mm+"struct mman::pc_video_height"
movl $0xb8000,mm+"struct mman::pc_video_framebuffer"
movl $0x8000,mm+"struct mman::pc_video_framebuffer_size"
mov $0x1003,%ax # enable/disable VGA text blinking
#ifdef VGA_USE_BLINK
mov $1,%bx

View file

@ -2,21 +2,11 @@
#define COSMOPOLITAN_LIBC_VGA_VGA_INTERNAL_H_
/*
* VGA_TTY_HEIGHT, VGA_TTY_WIDTH, VGA_USE_WCS, & VGA_PERSNICKETY_STATUS are
* configuration knobs which can potentially be used to tweak the features
* to be compiled into our VGA teletypewriter support.
* VGA_USE_WCS, VGA_USE_BLINK, & VGA_PERSNICKETY_STATUS are configuration
* knobs which can potentially be used to tweak the features to be compiled
* into our VGA teletypewriter support.
*/
/**
* Height of the video screen, in character units. Undefine if the height
* may vary at runtime.
*/
#define VGA_TTY_HEIGHT 25
/**
* Width of the video screen, in character units. Undefine if the width may
* vary at runtime.
*/
#define VGA_TTY_WIDTH 80
/**
* If VGA_USE_WCS is defined, the tty code can maintain an array of the
* Unicode characters "underlying" the 8-bit (or 9-bit) characters that are
@ -114,12 +104,7 @@ struct VgaTextCharCell {
struct Tty {
unsigned short y, x;
#ifndef VGA_TTY_HEIGHT
unsigned short yn;
#endif
#ifndef VGA_TTY_WIDTH
unsigned short xn;
#endif
unsigned short yn, xn;
uint32_t u8;
uint32_t n8;
uint32_t pr;

View file

@ -61,7 +61,9 @@ ssize_t sys_writev_vga(struct Fd *fd, const struct iovec *iov, int iovlen) {
__attribute__((__constructor__)) static textstartup void _vga_init(void) {
if (IsMetal()) {
struct mman *mm = (struct mman *)(BANE + 0x0500);
void * const vid_buf = (void *)(BANE + 0xb8000ull);
unsigned short height = mm->pc_video_height, width = mm->pc_video_width;
void * vid_buf = (void *)(BANE + mm->pc_video_framebuffer);
size_t vid_buf_sz = mm->pc_video_framebuffer_size;
/*
* Get the initial cursor position from the BIOS data area. Also get
* the height (in scan lines) of each character; this is used to set the
@ -76,13 +78,13 @@ __attribute__((__constructor__)) static textstartup void _vga_init(void) {
if (chr_ht_hi != 0 || chr_ht > 32)
chr_ht = 32;
/* Make sure the video buffer is mapped into virtual memory. */
__invert_memory_area(mm, __get_pml4t(), (uint64_t)vid_buf,
2 * VGA_TTY_HEIGHT * VGA_TTY_WIDTH, PAGE_RW);
__invert_memory_area(mm, __get_pml4t(), (uint64_t)vid_buf, vid_buf_sz,
PAGE_RW);
/*
* Initialize our tty structure from the current screen contents,
* current cursor position, & character height.
*/
_StartTty(&_vga_tty, VGA_TTY_HEIGHT, VGA_TTY_WIDTH, pos.row, pos.col,
chr_ht, vid_buf, vga_wcs);
_StartTty(&_vga_tty, height, width, pos.row, pos.col, chr_ht,
vid_buf, vga_wcs);
}
}