/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * The loader's user interface, shared by both firmwares. * * This is the first piece of the two loaders that is genuinely common code * rather than a contract they both honour. It can be, because the difference * between BIOS and UEFI is entirely in how you *obtain* a framebuffer -- VBE in * real mode, or GOP -- and not in what you do with one afterwards. By the time * there is a base address, a size and a stride, there is nothing firmware- * specific left to say. * * Everything here draws and nothing here decides. No disk, no memory map, no * mode setting: a caller hands over a framebuffer and asks for pixels. That is * what makes it compilable into a 16/32/64-bit BIOS loader and into a PE/COFF * UEFI application without either of them leaking into it. * * Types are spelled out rather than taken from a header, because the two * callers do not agree on one: the BIOS side has uchar/uint32 from the kernel * tree, the UEFI side has UINT8/UINT32 from the EFI headers, and this file has * to compile inside both. */ #ifndef SCHOS_BOOT_UI_H #define SCHOS_BOOT_UI_H typedef unsigned char ui_u8; typedef unsigned short ui_u16; typedef unsigned int ui_u32; typedef unsigned long long ui_u64; /* A linear framebuffer, 32 bits per pixel. Both firmwares can produce one and * neither can produce anything this code could use if they could not. */ struct ui_fb { ui_u8 *base; ui_u32 width; ui_u32 height; ui_u32 stride; /* bytes per row, from the driver -- never width*4 */ }; /* Hand over the framebuffer. Passing a null base, or a zero size, leaves the * UI inert: every call below then does nothing, so a caller with no display * does not need to guard each one. */ void ui_init(const struct ui_fb *fb); int ui_active(void); ui_u32 ui_width(void); ui_u32 ui_height(void); void ui_clear(void); void ui_fill_rect(int x, int y, int w, int h, ui_u32 colour); void ui_text(int x, int y, const char *s, ui_u32 colour, ui_u32 bg); void ui_text_centered(int y, const char *s, ui_u32 colour); /* The logo, centred horizontally, top-left at the given y, scaled to `w` * pixels wide. Downscaled from the source mask -- never up, which would only * make it soft. */ void ui_logo(int y, int w); /* The mark's width, which is also the progress bar's. One number, because the * two being the same width is the whole arrangement. */ int ui_mark_width(void); /* The splash: the mark, and the bar beneath it. * * No product name: the name is *in* the mark, and setting it again underneath * is the kind of thing that reads as a placeholder nobody removed. * * Laid out from the centre outwards rather than from the top down, so it looks * the same at 800x600 and at 1600x1200 instead of drifting up the screen as the * mode grows. */ void ui_splash(const char *subtitle); /* A menu, drawn as a panel. The caller owns the keyboard: this draws a state * and returns, so the same function serves a firmware with INT 16h and one with * a UEFI text-input protocol without either appearing in here. */ void ui_menu(const char *title, const char *const *items, int n, int selected, const char *hint); /* A panel of label/value rows -- the system information screen. */ void ui_panel(const char *title, const char *const *labels, const char *const *values, int n, const char *hint); /* The progress bar. `total` is whatever unit the caller counts in; ticks are * cumulative, and the bar only ever moves forward. */ void ui_progress_begin(const char *label, ui_u32 total); void ui_progress_label(const char *label); void ui_progress_tick(ui_u32 done); void ui_progress_end(void); #endif /* SCHOS_BOOT_UI_H */