loader: implement framebuffer console
Draw console on efi. Add vbe framebuffer for BIOS loader (vbe off, vbe on, vbe list, vbe set xxx). autoload font (/boot/fonts) based on resolution and font size. Add command loadfont (set font by file) and variable screen.font (set font by size). Pass loaded font to kernel. Export variables: screen.height screen.width screen.depth Add gfx primitives to draw the screen and put png image on the screen. Rework menu draw to iterate list of consoles to enamble device specific output. Probably something else I forgot... Relnotes: yes Differential Revision: https://reviews.freebsd.org/D27420
This commit is contained in:
parent
bd03acedb8
commit
3630506b9d
@ -25,6 +25,8 @@ S.${MK_FORTH}+= forth
|
||||
S.${MK_LOADER_LUA}+= liblua
|
||||
S.${MK_LOADER_LUA}+= lua
|
||||
S.yes+= defaults
|
||||
S.yes+= fonts
|
||||
S.yes+= images
|
||||
S.yes+= man
|
||||
|
||||
.if ${MK_FORTH} != "no"
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/linker_set.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "readin.h"
|
||||
|
||||
@ -119,6 +120,8 @@ struct console
|
||||
};
|
||||
extern struct console *consoles[];
|
||||
void cons_probe(void);
|
||||
bool cons_update_mode(bool);
|
||||
void autoload_font(bool);
|
||||
|
||||
/*
|
||||
* Plug-and-play enumerator/configurator interface.
|
||||
@ -258,6 +261,8 @@ int file_addmodule(struct preloaded_file *, char *, int,
|
||||
struct kernel_module **);
|
||||
void file_removemetadata(struct preloaded_file *fp);
|
||||
|
||||
vm_offset_t build_font_module(vm_offset_t);
|
||||
|
||||
/* MI module loaders */
|
||||
#ifdef __elfN
|
||||
/* Relocation types. */
|
||||
|
2641
stand/common/gfx_fb.c
Normal file
2641
stand/common/gfx_fb.c
Normal file
File diff suppressed because it is too large
Load Diff
274
stand/common/gfx_fb.h
Normal file
274
stand/common/gfx_fb.h
Normal file
@ -0,0 +1,274 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright 2020 Toomas Soome
|
||||
* Copyright 2020 RackTop Systems, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _GFX_FB_H
|
||||
#define _GFX_FB_H
|
||||
|
||||
#include <sys/font.h>
|
||||
#include <teken.h>
|
||||
#include <stdbool.h>
|
||||
#include <machine/metadata.h>
|
||||
#include <pnglite.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define EDID_MAGIC { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }
|
||||
|
||||
struct edid_header {
|
||||
uint8_t header[8]; /* fixed header pattern */
|
||||
uint16_t manufacturer_id;
|
||||
uint16_t product_code;
|
||||
uint32_t serial_number;
|
||||
uint8_t week_of_manufacture;
|
||||
uint8_t year_of_manufacture;
|
||||
uint8_t version;
|
||||
uint8_t revision;
|
||||
};
|
||||
|
||||
struct edid_basic_display_parameters {
|
||||
uint8_t video_input_parameters;
|
||||
uint8_t max_horizontal_image_size;
|
||||
uint8_t max_vertical_image_size;
|
||||
uint8_t display_gamma;
|
||||
uint8_t supported_features;
|
||||
};
|
||||
|
||||
struct edid_chromaticity_coordinates {
|
||||
uint8_t red_green_lo;
|
||||
uint8_t blue_white_lo;
|
||||
uint8_t red_x_hi;
|
||||
uint8_t red_y_hi;
|
||||
uint8_t green_x_hi;
|
||||
uint8_t green_y_hi;
|
||||
uint8_t blue_x_hi;
|
||||
uint8_t blue_y_hi;
|
||||
uint8_t white_x_hi;
|
||||
uint8_t white_y_hi;
|
||||
};
|
||||
|
||||
struct edid_detailed_timings {
|
||||
uint16_t pixel_clock;
|
||||
uint8_t horizontal_active_lo;
|
||||
uint8_t horizontal_blanking_lo;
|
||||
uint8_t horizontal_hi;
|
||||
uint8_t vertical_active_lo;
|
||||
uint8_t vertical_blanking_lo;
|
||||
uint8_t vertical_hi;
|
||||
uint8_t horizontal_sync_offset_lo;
|
||||
uint8_t horizontal_sync_pulse_width_lo;
|
||||
uint8_t vertical_sync_lo;
|
||||
uint8_t sync_hi;
|
||||
uint8_t horizontal_image_size_lo;
|
||||
uint8_t vertical_image_size_lo;
|
||||
uint8_t image_size_hi;
|
||||
uint8_t horizontal_border;
|
||||
uint8_t vertical_border;
|
||||
uint8_t features;
|
||||
};
|
||||
|
||||
struct vesa_edid_info {
|
||||
struct edid_header header;
|
||||
struct edid_basic_display_parameters display;
|
||||
#define EDID_FEATURE_PREFERRED_TIMING_MODE (1 << 1)
|
||||
struct edid_chromaticity_coordinates chromaticity;
|
||||
uint8_t established_timings_1;
|
||||
uint8_t established_timings_2;
|
||||
uint8_t manufacturer_reserved_timings;
|
||||
uint16_t standard_timings[8];
|
||||
struct edid_detailed_timings detailed_timings[4];
|
||||
uint8_t number_of_extensions;
|
||||
uint8_t checksum;
|
||||
} __packed;
|
||||
|
||||
#define STD_TIMINGS 8
|
||||
#define DET_TIMINGS 4
|
||||
|
||||
#define HSIZE(x) (((x & 0xff) + 31) * 8)
|
||||
#define RATIO(x) ((x & 0xC000) >> 14)
|
||||
#define RATIO1_1 0
|
||||
/* EDID Ver. 1.3 redefined this */
|
||||
#define RATIO16_10 RATIO1_1
|
||||
#define RATIO4_3 1
|
||||
#define RATIO5_4 2
|
||||
#define RATIO16_9 3
|
||||
|
||||
/*
|
||||
* Number of pixels and lines is 12-bit int, valid values 0-4095.
|
||||
*/
|
||||
#define EDID_MAX_PIXELS 4095
|
||||
#define EDID_MAX_LINES 4095
|
||||
|
||||
#define GET_EDID_INFO_WIDTH(edid_info, timings_num) \
|
||||
((edid_info)->detailed_timings[(timings_num)].horizontal_active_lo | \
|
||||
(((uint32_t)(edid_info)->detailed_timings[(timings_num)].horizontal_hi & \
|
||||
0xf0) << 4))
|
||||
|
||||
#define GET_EDID_INFO_HEIGHT(edid_info, timings_num) \
|
||||
((edid_info)->detailed_timings[(timings_num)].vertical_active_lo | \
|
||||
(((uint32_t)(edid_info)->detailed_timings[(timings_num)].vertical_hi & \
|
||||
0xf0) << 4))
|
||||
|
||||
struct resolution {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
TAILQ_ENTRY(resolution) next;
|
||||
};
|
||||
|
||||
typedef TAILQ_HEAD(edid_resolution, resolution) edid_res_list_t;
|
||||
|
||||
struct vesa_flat_panel_info {
|
||||
uint16_t HSize; /* Horizontal Size in Pixels */
|
||||
uint16_t VSize; /* Vertical Size in Lines */
|
||||
uint16_t FPType; /* Flat Panel Type */
|
||||
uint8_t RedBPP; /* Red Bits Per Primary */
|
||||
uint8_t GreenBPP; /* Green Bits Per Primary */
|
||||
uint8_t BlueBPP; /* Blue Bits Per Primary */
|
||||
uint8_t ReservedBPP; /* Reserved Bits Per Primary */
|
||||
uint32_t RsvdOffScrnMemSize; /* Size in KB of Offscreen Memory */
|
||||
uint32_t RsvdOffScrnMemPtr; /* Pointer to reserved offscreen memory */
|
||||
uint8_t Reserved[14]; /* remainder of FPInfo */
|
||||
} __packed;
|
||||
|
||||
#define COLOR_FORMAT_VGA 0
|
||||
#define COLOR_FORMAT_RGB 1
|
||||
#define NCOLORS 16
|
||||
#define NCMAP 256
|
||||
extern uint32_t cmap[NCMAP];
|
||||
|
||||
enum FB_TYPE {
|
||||
FB_TEXT = -1,
|
||||
FB_GOP,
|
||||
FB_UGA,
|
||||
FB_VBE
|
||||
};
|
||||
|
||||
enum COLOR_TYPE {
|
||||
CT_INDEXED,
|
||||
CT_RGB
|
||||
};
|
||||
|
||||
struct gen_fb {
|
||||
uint64_t fb_addr;
|
||||
uint64_t fb_size;
|
||||
uint32_t fb_height;
|
||||
uint32_t fb_width;
|
||||
uint32_t fb_stride;
|
||||
uint32_t fb_mask_red;
|
||||
uint32_t fb_mask_green;
|
||||
uint32_t fb_mask_blue;
|
||||
uint32_t fb_mask_reserved;
|
||||
uint32_t fb_bpp;
|
||||
};
|
||||
|
||||
typedef struct teken_gfx {
|
||||
enum FB_TYPE tg_fb_type;
|
||||
enum COLOR_TYPE tg_ctype;
|
||||
unsigned tg_mode;
|
||||
teken_t tg_teken; /* Teken core */
|
||||
teken_pos_t tg_cursor; /* Where cursor was drawn */
|
||||
bool tg_cursor_visible;
|
||||
teken_pos_t tg_tp; /* Terminal dimensions */
|
||||
teken_pos_t tg_origin; /* Point of origin in pixels */
|
||||
uint8_t *tg_glyph; /* Memory for glyph */
|
||||
size_t tg_glyph_size;
|
||||
struct vt_font tg_font;
|
||||
struct gen_fb tg_fb;
|
||||
teken_funcs_t *tg_functions;
|
||||
void *tg_private;
|
||||
} teken_gfx_t;
|
||||
|
||||
extern font_list_t fonts;
|
||||
extern teken_gfx_t gfx_state;
|
||||
|
||||
typedef enum {
|
||||
GfxFbBltVideoFill,
|
||||
GfxFbBltVideoToBltBuffer,
|
||||
GfxFbBltBufferToVideo,
|
||||
GfxFbBltVideoToVideo,
|
||||
GfxFbBltOperationMax,
|
||||
} GFXFB_BLT_OPERATION;
|
||||
|
||||
int gfxfb_blt(void *, GFXFB_BLT_OPERATION, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
|
||||
int generate_cons_palette(uint32_t *, int, uint32_t, int, uint32_t, int,
|
||||
uint32_t, int);
|
||||
bool console_update_mode(bool);
|
||||
void setup_font(teken_gfx_t *, teken_unit_t, teken_unit_t);
|
||||
uint8_t *font_lookup(const struct vt_font *, teken_char_t,
|
||||
const teken_attr_t *);
|
||||
void bios_text_font(bool);
|
||||
|
||||
/* teken callbacks. */
|
||||
tf_cursor_t gfx_fb_cursor;
|
||||
tf_putchar_t gfx_fb_putchar;
|
||||
tf_fill_t gfx_fb_fill;
|
||||
tf_copy_t gfx_fb_copy;
|
||||
tf_param_t gfx_fb_param;
|
||||
|
||||
/* Screen buffer element */
|
||||
struct text_pixel {
|
||||
teken_char_t c;
|
||||
teken_attr_t a;
|
||||
};
|
||||
|
||||
extern const int cons_to_vga_colors[NCOLORS];
|
||||
|
||||
/* Screen buffer to track changes on the terminal screen. */
|
||||
extern struct text_pixel *screen_buffer;
|
||||
bool is_same_pixel(struct text_pixel *, struct text_pixel *);
|
||||
|
||||
bool gfx_get_edid_resolution(struct vesa_edid_info *, edid_res_list_t *);
|
||||
void gfx_framework_init(void);
|
||||
void gfx_fb_cons_display(uint32_t, uint32_t, uint32_t, uint32_t, void *);
|
||||
void gfx_fb_setpixel(uint32_t, uint32_t);
|
||||
void gfx_fb_drawrect(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
void gfx_term_drawrect(uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
void gfx_fb_line(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
void gfx_fb_bezier(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t);
|
||||
|
||||
#define FL_PUTIMAGE_BORDER 0x1
|
||||
#define FL_PUTIMAGE_NOSCROLL 0x2
|
||||
#define FL_PUTIMAGE_DEBUG 0x80
|
||||
|
||||
int gfx_fb_putimage(png_t *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
bool gfx_parse_mode_str(char *, int *, int *, int *);
|
||||
void term_image_display(teken_gfx_t *, const teken_rect_t *);
|
||||
|
||||
void reset_font_flags(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GFX_FB_H */
|
@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/module.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/stdint.h>
|
||||
#include <sys/font.h>
|
||||
#include <gfx_fb.h>
|
||||
|
||||
#if defined(LOADER_FDT_SUPPORT)
|
||||
#include <fdt_platform.h>
|
||||
@ -91,7 +93,6 @@ static char *kld_ext_list[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* load an object, either a disk file or code module.
|
||||
*
|
||||
@ -616,6 +617,92 @@ file_load_dependencies(struct preloaded_file *base_file)
|
||||
return (error);
|
||||
}
|
||||
|
||||
vm_offset_t
|
||||
build_font_module(vm_offset_t addr)
|
||||
{
|
||||
vt_font_bitmap_data_t *bd;
|
||||
struct vt_font *fd;
|
||||
struct preloaded_file *fp;
|
||||
size_t size;
|
||||
uint32_t checksum;
|
||||
int i;
|
||||
struct font_info fi;
|
||||
struct fontlist *fl;
|
||||
uint64_t fontp;
|
||||
|
||||
if (STAILQ_EMPTY(&fonts))
|
||||
return (addr);
|
||||
|
||||
/* We can't load first */
|
||||
if ((file_findfile(NULL, NULL)) == NULL) {
|
||||
printf("Can not load font module: %s\n",
|
||||
"the kernel is not loaded");
|
||||
return (addr);
|
||||
}
|
||||
|
||||
/* helper pointers */
|
||||
bd = NULL;
|
||||
STAILQ_FOREACH(fl, &fonts, font_next) {
|
||||
if (gfx_state.tg_font.vf_width == fl->font_data->vfbd_width &&
|
||||
gfx_state.tg_font.vf_height == fl->font_data->vfbd_height) {
|
||||
/*
|
||||
* Kernel does have better built in font.
|
||||
*/
|
||||
if (fl->font_flags == FONT_BUILTIN)
|
||||
return (addr);
|
||||
|
||||
bd = fl->font_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bd == NULL)
|
||||
return (addr);
|
||||
fd = bd->vfbd_font;
|
||||
|
||||
fi.fi_width = fd->vf_width;
|
||||
checksum = fi.fi_width;
|
||||
fi.fi_height = fd->vf_height;
|
||||
checksum += fi.fi_height;
|
||||
fi.fi_bitmap_size = bd->vfbd_uncompressed_size;
|
||||
checksum += fi.fi_bitmap_size;
|
||||
|
||||
size = roundup2(sizeof (struct font_info), 8);
|
||||
for (i = 0; i < VFNT_MAPS; i++) {
|
||||
fi.fi_map_count[i] = fd->vf_map_count[i];
|
||||
checksum += fi.fi_map_count[i];
|
||||
size += fd->vf_map_count[i] * sizeof (struct vfnt_map);
|
||||
size += roundup2(size, 8);
|
||||
}
|
||||
size += bd->vfbd_uncompressed_size;
|
||||
|
||||
fi.fi_checksum = -checksum;
|
||||
|
||||
fp = file_findfile(NULL, "elf kernel");
|
||||
if (fp == NULL)
|
||||
fp = file_findfile(NULL, "elf64 kernel");
|
||||
if (fp == NULL)
|
||||
panic("can't find kernel file");
|
||||
|
||||
fontp = addr;
|
||||
addr += archsw.arch_copyin(&fi, addr, sizeof (struct font_info));
|
||||
addr = roundup2(addr, 8);
|
||||
|
||||
/* Copy maps. */
|
||||
for (i = 0; i < VFNT_MAPS; i++) {
|
||||
if (fd->vf_map_count[i] != 0) {
|
||||
addr += archsw.arch_copyin(fd->vf_map[i], addr,
|
||||
fd->vf_map_count[i] * sizeof (struct vfnt_map));
|
||||
addr = roundup2(addr, 8);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the bitmap. */
|
||||
addr += archsw.arch_copyin(fd->vf_bytes, addr, fi.fi_bitmap_size);
|
||||
|
||||
/* Looks OK so far; populate control structure */
|
||||
file_addmetadata(fp, MODINFOMD_FONT, sizeof(fontp), &fontp);
|
||||
return (addr);
|
||||
}
|
||||
|
||||
#ifdef LOADER_VERIEXEC_VECTX
|
||||
#define VECTX_HANDLE(fd) vctx
|
||||
|
@ -238,7 +238,9 @@ replacing it with
|
||||
.Dq spinning
|
||||
character (useful for embedded products and such).
|
||||
.It Va efi_max_resolution
|
||||
Specify the maximum desired resolution for the EFI console.
|
||||
.It Va vbe_max_resolution
|
||||
Specify the maximum desired resolution for the EFI or VESA BIOS Extension (VBE)
|
||||
framebuffer console.
|
||||
The following values are accepted:
|
||||
.Bl -column "WidthxHeight"
|
||||
.It Sy Value Ta Sy Resolution
|
||||
|
@ -108,7 +108,6 @@ void efi_time_init(void);
|
||||
void efi_time_fini(void);
|
||||
|
||||
int parse_uefi_con_out(void);
|
||||
bool efi_cons_update_mode(void);
|
||||
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
|
||||
|
||||
EFI_STATUS main(int argc, CHAR16 *argv[]);
|
||||
|
@ -49,7 +49,7 @@ CFLAGS+= -fPIC -mno-red-zone
|
||||
.endif
|
||||
CFLAGS+= -I${EFIINC}
|
||||
CFLAGS+= -I${EFIINCMD}
|
||||
CFLAGS.efi_console.c+= -I${SRCTOP}/sys/teken
|
||||
CFLAGS.efi_console.c+= -I${SRCTOP}/sys/teken -I${SRCTOP}/contrib/pnglite
|
||||
CFLAGS.teken.c+= -I${SRCTOP}/sys/teken
|
||||
.if ${MK_LOADER_ZFS} != "no"
|
||||
CFLAGS+= -I${ZFSSRC}
|
||||
|
@ -27,17 +27,22 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
#include <teken.h>
|
||||
#include <sys/reboot.h>
|
||||
|
||||
#include <machine/metadata.h>
|
||||
#include <gfx_fb.h>
|
||||
#include "bootstrap.h"
|
||||
|
||||
extern EFI_GUID gop_guid;
|
||||
extern int efi_find_framebuffer(struct efi_fb *efifb);
|
||||
static EFI_GUID simple_input_ex_guid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
|
||||
static SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
|
||||
static SIMPLE_INPUT_INTERFACE *conin;
|
||||
static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *coninex;
|
||||
static bool efi_started;
|
||||
|
||||
static int mode; /* Does ConOut have serial console? */
|
||||
|
||||
@ -59,6 +64,9 @@ void HO(void);
|
||||
void end_term(void);
|
||||
#endif
|
||||
|
||||
#define TEXT_ROWS 24
|
||||
#define TEXT_COLS 80
|
||||
|
||||
static tf_bell_t efi_cons_bell;
|
||||
static tf_cursor_t efi_text_cursor;
|
||||
static tf_putchar_t efi_text_putchar;
|
||||
@ -77,16 +85,16 @@ static teken_funcs_t tf = {
|
||||
.tf_respond = efi_cons_respond,
|
||||
};
|
||||
|
||||
teken_t teken;
|
||||
teken_pos_t tp;
|
||||
|
||||
struct text_pixel {
|
||||
teken_char_t c;
|
||||
teken_attr_t a;
|
||||
static teken_funcs_t tfx = {
|
||||
.tf_bell = efi_cons_bell,
|
||||
.tf_cursor = gfx_fb_cursor,
|
||||
.tf_putchar = gfx_fb_putchar,
|
||||
.tf_fill = gfx_fb_fill,
|
||||
.tf_copy = gfx_fb_copy,
|
||||
.tf_param = gfx_fb_param,
|
||||
.tf_respond = efi_cons_respond,
|
||||
};
|
||||
|
||||
static struct text_pixel *buffer;
|
||||
|
||||
#define KEYBUFSZ 10
|
||||
static unsigned keybuf[KEYBUFSZ]; /* keybuf for extended codes */
|
||||
static int key_pending;
|
||||
@ -116,6 +124,7 @@ void efi_cons_putchar(int);
|
||||
int efi_cons_getchar(void);
|
||||
void efi_cons_efiputchar(int);
|
||||
int efi_cons_poll(void);
|
||||
static void cons_draw_frame(teken_attr_t *);
|
||||
|
||||
struct console efi_console = {
|
||||
"efi",
|
||||
@ -128,6 +137,28 @@ struct console efi_console = {
|
||||
efi_cons_poll
|
||||
};
|
||||
|
||||
/*
|
||||
* This function is used to mark a rectangular image area so the scrolling
|
||||
* will know we need to copy the data from there.
|
||||
*/
|
||||
void
|
||||
term_image_display(teken_gfx_t *state, const teken_rect_t *r)
|
||||
{
|
||||
teken_pos_t p;
|
||||
int idx;
|
||||
|
||||
for (p.tp_row = r->tr_begin.tp_row;
|
||||
p.tp_row < r->tr_end.tp_row; p.tp_row++) {
|
||||
for (p.tp_col = r->tr_begin.tp_col;
|
||||
p.tp_col < r->tr_end.tp_col; p.tp_col++) {
|
||||
idx = p.tp_col + p.tp_row * state->tg_tp.tp_col;
|
||||
if (idx >= state->tg_tp.tp_col * state->tg_tp.tp_row)
|
||||
return;
|
||||
screen_buffer[idx].a.ta_format |= TF_IMAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Not implemented.
|
||||
*/
|
||||
@ -137,33 +168,30 @@ efi_cons_bell(void *s __unused)
|
||||
}
|
||||
|
||||
static void
|
||||
efi_text_cursor(void *s __unused, const teken_pos_t *p)
|
||||
efi_text_cursor(void *arg, const teken_pos_t *p)
|
||||
{
|
||||
UINTN row, col;
|
||||
teken_gfx_t *state = arg;
|
||||
UINTN col, row;
|
||||
|
||||
(void) conout->QueryMode(conout, conout->Mode->Mode, &col, &row);
|
||||
|
||||
if (p->tp_col == col)
|
||||
col = p->tp_col - 1;
|
||||
else
|
||||
col = p->tp_col;
|
||||
|
||||
if (p->tp_row == row)
|
||||
row = p->tp_row - 1;
|
||||
else
|
||||
row = p->tp_row;
|
||||
if (p->tp_row >= state->tg_tp.tp_row)
|
||||
row = state->tg_tp.tp_row - 1;
|
||||
|
||||
col = p->tp_col;
|
||||
if (p->tp_col >= state->tg_tp.tp_col)
|
||||
col = state->tg_tp.tp_col - 1;
|
||||
|
||||
conout->SetCursorPosition(conout, col, row);
|
||||
}
|
||||
|
||||
static void
|
||||
efi_text_printchar(const teken_pos_t *p, bool autoscroll)
|
||||
efi_text_printchar(teken_gfx_t *state, const teken_pos_t *p, bool autoscroll)
|
||||
{
|
||||
UINTN a, attr;
|
||||
struct text_pixel *px;
|
||||
teken_color_t fg, bg, tmp;
|
||||
|
||||
px = buffer + p->tp_col + p->tp_row * tp.tp_col;
|
||||
px = screen_buffer + p->tp_col + p->tp_row * state->tg_tp.tp_col;
|
||||
a = conout->Mode->Attribute;
|
||||
|
||||
fg = teken_256to16(px->a.ta_fgcolor);
|
||||
@ -184,10 +212,10 @@ efi_text_printchar(const teken_pos_t *p, bool autoscroll)
|
||||
|
||||
conout->SetCursorPosition(conout, p->tp_col, p->tp_row);
|
||||
|
||||
/* to prvent autoscroll, skip print of lower right char */
|
||||
/* to prevent autoscroll, skip print of lower right char */
|
||||
if (!autoscroll &&
|
||||
p->tp_row == tp.tp_row - 1 &&
|
||||
p->tp_col == tp.tp_col - 1)
|
||||
p->tp_row == state->tg_tp.tp_row - 1 &&
|
||||
p->tp_col == state->tg_tp.tp_col - 1)
|
||||
return;
|
||||
|
||||
(void) conout->SetAttribute(conout, attr);
|
||||
@ -196,58 +224,80 @@ efi_text_printchar(const teken_pos_t *p, bool autoscroll)
|
||||
}
|
||||
|
||||
static void
|
||||
efi_text_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c,
|
||||
efi_text_putchar(void *s, const teken_pos_t *p, teken_char_t c,
|
||||
const teken_attr_t *a)
|
||||
{
|
||||
teken_gfx_t *state = s;
|
||||
EFI_STATUS status;
|
||||
int idx;
|
||||
|
||||
idx = p->tp_col + p->tp_row * tp.tp_col;
|
||||
buffer[idx].c = c;
|
||||
buffer[idx].a = *a;
|
||||
efi_text_printchar(p, false);
|
||||
idx = p->tp_col + p->tp_row * state->tg_tp.tp_col;
|
||||
if (idx >= state->tg_tp.tp_col * state->tg_tp.tp_row)
|
||||
return;
|
||||
|
||||
screen_buffer[idx].c = c;
|
||||
screen_buffer[idx].a = *a;
|
||||
|
||||
efi_text_printchar(s, p, false);
|
||||
}
|
||||
|
||||
static void
|
||||
efi_text_fill(void *s, const teken_rect_t *r, teken_char_t c,
|
||||
efi_text_fill(void *arg, const teken_rect_t *r, teken_char_t c,
|
||||
const teken_attr_t *a)
|
||||
{
|
||||
teken_gfx_t *state = arg;
|
||||
teken_pos_t p;
|
||||
UINTN row, col;
|
||||
|
||||
(void) conout->QueryMode(conout, conout->Mode->Mode, &col, &row);
|
||||
|
||||
if (state->tg_cursor_visible)
|
||||
conout->EnableCursor(conout, FALSE);
|
||||
for (p.tp_row = r->tr_begin.tp_row; p.tp_row < r->tr_end.tp_row;
|
||||
p.tp_row++)
|
||||
for (p.tp_col = r->tr_begin.tp_col;
|
||||
p.tp_col < r->tr_end.tp_col; p.tp_col++)
|
||||
efi_text_putchar(s, &p, c, a);
|
||||
efi_text_putchar(state, &p, c, a);
|
||||
if (state->tg_cursor_visible)
|
||||
conout->EnableCursor(conout, TRUE);
|
||||
}
|
||||
|
||||
static bool
|
||||
efi_same_pixel(struct text_pixel *px1, struct text_pixel *px2)
|
||||
static void
|
||||
efi_text_copy_line(teken_gfx_t *state, int ncol, teken_pos_t *s,
|
||||
teken_pos_t *d, bool scroll)
|
||||
{
|
||||
if (px1->c != px2->c)
|
||||
return (false);
|
||||
unsigned soffset, doffset;
|
||||
teken_pos_t sp, dp;
|
||||
int x;
|
||||
|
||||
if (px1->a.ta_format != px2->a.ta_format)
|
||||
return (false);
|
||||
if (px1->a.ta_fgcolor != px2->a.ta_fgcolor)
|
||||
return (false);
|
||||
if (px1->a.ta_bgcolor != px2->a.ta_bgcolor)
|
||||
return (false);
|
||||
soffset = s->tp_col + s->tp_row * state->tg_tp.tp_col;
|
||||
doffset = d->tp_col + d->tp_row * state->tg_tp.tp_col;
|
||||
|
||||
return (true);
|
||||
sp = *s;
|
||||
dp = *d;
|
||||
for (x = 0; x < ncol; x++) {
|
||||
sp.tp_col = s->tp_col + x;
|
||||
dp.tp_col = d->tp_col + x;
|
||||
if (!is_same_pixel(&screen_buffer[soffset + x],
|
||||
&screen_buffer[doffset + x])) {
|
||||
screen_buffer[doffset + x] =
|
||||
screen_buffer[soffset + x];
|
||||
if (!scroll)
|
||||
efi_text_printchar(state, &dp, false);
|
||||
} else if (scroll) {
|
||||
/* Draw last char and trigger scroll. */
|
||||
if (dp.tp_col + 1 == state->tg_tp.tp_col &&
|
||||
dp.tp_row + 1 == state->tg_tp.tp_row) {
|
||||
efi_text_printchar(state, &dp, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
efi_text_copy(void *ptr __unused, const teken_rect_t *r, const teken_pos_t *p)
|
||||
efi_text_copy(void *arg, const teken_rect_t *r, const teken_pos_t *p)
|
||||
{
|
||||
int srow, drow;
|
||||
int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */
|
||||
teken_gfx_t *state = arg;
|
||||
unsigned doffset, soffset;
|
||||
teken_pos_t d, s;
|
||||
int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */
|
||||
bool scroll = false;
|
||||
|
||||
/*
|
||||
@ -262,90 +312,47 @@ efi_text_copy(void *ptr __unused, const teken_rect_t *r, const teken_pos_t *p)
|
||||
* Check if we do copy whole screen.
|
||||
*/
|
||||
if (p->tp_row == 0 && p->tp_col == 0 &&
|
||||
nrow == tp.tp_row - 2 && ncol == tp.tp_col - 2)
|
||||
nrow == state->tg_tp.tp_row - 2 && ncol == state->tg_tp.tp_col - 2)
|
||||
scroll = true;
|
||||
|
||||
soffset = r->tr_begin.tp_col + r->tr_begin.tp_row * state->tg_tp.tp_col;
|
||||
doffset = p->tp_col + p->tp_row * state->tg_tp.tp_col;
|
||||
|
||||
/* remove the cursor */
|
||||
if (state->tg_cursor_visible)
|
||||
conout->EnableCursor(conout, FALSE);
|
||||
if (p->tp_row < r->tr_begin.tp_row) {
|
||||
/* Copy from bottom to top. */
|
||||
for (y = 0; y < nrow; y++) {
|
||||
d.tp_row = p->tp_row + y;
|
||||
s.tp_row = r->tr_begin.tp_row + y;
|
||||
drow = d.tp_row * tp.tp_col;
|
||||
srow = s.tp_row * tp.tp_col;
|
||||
for (x = 0; x < ncol; x++) {
|
||||
d.tp_col = p->tp_col + x;
|
||||
s.tp_col = r->tr_begin.tp_col + x;
|
||||
|
||||
if (!efi_same_pixel(
|
||||
&buffer[d.tp_col + drow],
|
||||
&buffer[s.tp_col + srow])) {
|
||||
buffer[d.tp_col + drow] =
|
||||
buffer[s.tp_col + srow];
|
||||
if (!scroll)
|
||||
efi_text_printchar(&d, false);
|
||||
} else if (scroll) {
|
||||
/*
|
||||
* Draw last char and trigger
|
||||
* scroll.
|
||||
* Copy line by line.
|
||||
*/
|
||||
if (y == nrow - 1 &&
|
||||
x == ncol - 1) {
|
||||
efi_text_printchar(&d, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (doffset <= soffset) {
|
||||
s = r->tr_begin;
|
||||
d = *p;
|
||||
for (y = 0; y < nrow; y++) {
|
||||
s.tp_row = r->tr_begin.tp_row + y;
|
||||
d.tp_row = p->tp_row + y;
|
||||
|
||||
efi_text_copy_line(state, ncol, &s, &d, scroll);
|
||||
}
|
||||
} else {
|
||||
/* Copy from top to bottom. */
|
||||
if (p->tp_col < r->tr_begin.tp_col) {
|
||||
/* Copy from right to left. */
|
||||
for (y = nrow - 1; y >= 0; y--) {
|
||||
d.tp_row = p->tp_row + y;
|
||||
s.tp_row = r->tr_begin.tp_row + y;
|
||||
drow = d.tp_row * tp.tp_col;
|
||||
srow = s.tp_row * tp.tp_col;
|
||||
for (x = 0; x < ncol; x++) {
|
||||
d.tp_col = p->tp_col + x;
|
||||
s.tp_col = r->tr_begin.tp_col + x;
|
||||
|
||||
if (!efi_same_pixel(
|
||||
&buffer[d.tp_col + drow],
|
||||
&buffer[s.tp_col + srow])) {
|
||||
buffer[d.tp_col + drow] =
|
||||
buffer[s.tp_col + srow];
|
||||
efi_text_printchar(&d, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Copy from left to right. */
|
||||
for (y = nrow - 1; y >= 0; y--) {
|
||||
d.tp_row = p->tp_row + y;
|
||||
s.tp_row = r->tr_begin.tp_row + y;
|
||||
drow = d.tp_row * tp.tp_col;
|
||||
srow = s.tp_row * tp.tp_col;
|
||||
for (x = ncol - 1; x >= 0; x--) {
|
||||
d.tp_col = p->tp_col + x;
|
||||
s.tp_col = r->tr_begin.tp_col + x;
|
||||
|
||||
if (!efi_same_pixel(
|
||||
&buffer[d.tp_col + drow],
|
||||
&buffer[s.tp_col + srow])) {
|
||||
buffer[d.tp_col + drow] =
|
||||
buffer[s.tp_col + srow];
|
||||
efi_text_printchar(&d, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
efi_text_copy_line(state, ncol, &s, &d, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* display the cursor */
|
||||
if (state->tg_cursor_visible)
|
||||
conout->EnableCursor(conout, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
efi_text_param(void *s __unused, int cmd, unsigned int value)
|
||||
efi_text_param(void *arg, int cmd, unsigned int value)
|
||||
{
|
||||
teken_gfx_t *state = arg;
|
||||
|
||||
switch (cmd) {
|
||||
case TP_SETLOCALCURSOR:
|
||||
/*
|
||||
@ -357,10 +364,13 @@ efi_text_param(void *s __unused, int cmd, unsigned int value)
|
||||
value = (value == 1) ? 0 : 1;
|
||||
/* FALLTHROUGH */
|
||||
case TP_SHOWCURSOR:
|
||||
if (value == 1)
|
||||
if (value != 0) {
|
||||
conout->EnableCursor(conout, TRUE);
|
||||
else
|
||||
state->tg_cursor_visible = true;
|
||||
} else {
|
||||
conout->EnableCursor(conout, FALSE);
|
||||
state->tg_cursor_visible = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Not yet implemented */
|
||||
@ -470,7 +480,7 @@ efi_set_colors(struct env_var *ev, int flags, const void *value)
|
||||
evalue = value;
|
||||
}
|
||||
|
||||
ap = teken_get_defattr(&teken);
|
||||
ap = teken_get_defattr(&gfx_state.tg_teken);
|
||||
a = *ap;
|
||||
if (strcmp(ev->ev_name, "teken.fg_color") == 0) {
|
||||
/* is it already set? */
|
||||
@ -484,8 +494,15 @@ efi_set_colors(struct env_var *ev, int flags, const void *value)
|
||||
return (CMD_OK);
|
||||
a.ta_bgcolor = val;
|
||||
}
|
||||
|
||||
/* Improve visibility */
|
||||
if (a.ta_bgcolor == TC_WHITE)
|
||||
a.ta_bgcolor |= TC_LIGHT;
|
||||
|
||||
teken_set_defattr(&gfx_state.tg_teken, &a);
|
||||
cons_draw_frame(&a);
|
||||
env_setenv(ev->ev_name, flags | EV_NOHOOK, evalue, NULL, NULL);
|
||||
teken_set_defattr(&teken, &a);
|
||||
teken_input(&gfx_state.tg_teken, "\e[2J", 4);
|
||||
return (CMD_OK);
|
||||
}
|
||||
|
||||
@ -823,19 +840,100 @@ efi_term_emu(int c)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
env_screen_nounset(struct env_var *ev __unused)
|
||||
{
|
||||
if (gfx_state.tg_fb_type == FB_TEXT)
|
||||
return (0);
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
static void
|
||||
cons_draw_frame(teken_attr_t *a)
|
||||
{
|
||||
teken_attr_t attr = *a;
|
||||
teken_color_t fg = a->ta_fgcolor;
|
||||
|
||||
attr.ta_fgcolor = attr.ta_bgcolor;
|
||||
teken_set_defattr(&gfx_state.tg_teken, &attr);
|
||||
|
||||
gfx_fb_drawrect(0, 0, gfx_state.tg_fb.fb_width,
|
||||
gfx_state.tg_origin.tp_row, 1);
|
||||
gfx_fb_drawrect(0,
|
||||
gfx_state.tg_fb.fb_height - gfx_state.tg_origin.tp_row - 1,
|
||||
gfx_state.tg_fb.fb_width, gfx_state.tg_fb.fb_height, 1);
|
||||
gfx_fb_drawrect(0, gfx_state.tg_origin.tp_row,
|
||||
gfx_state.tg_origin.tp_col,
|
||||
gfx_state.tg_fb.fb_height - gfx_state.tg_origin.tp_row - 1, 1);
|
||||
gfx_fb_drawrect(
|
||||
gfx_state.tg_fb.fb_width - gfx_state.tg_origin.tp_col - 1,
|
||||
gfx_state.tg_origin.tp_row, gfx_state.tg_fb.fb_width,
|
||||
gfx_state.tg_fb.fb_height, 1);
|
||||
|
||||
attr.ta_fgcolor = fg;
|
||||
teken_set_defattr(&gfx_state.tg_teken, &attr);
|
||||
}
|
||||
|
||||
bool
|
||||
efi_cons_update_mode(void)
|
||||
cons_update_mode(bool use_gfx_mode)
|
||||
{
|
||||
UINTN cols, rows;
|
||||
const teken_attr_t *a;
|
||||
teken_attr_t attr;
|
||||
EFI_STATUS status;
|
||||
char env[8], *ptr;
|
||||
EFI_GRAPHICS_OUTPUT *gop = NULL;
|
||||
struct efi_fb efifb;
|
||||
char env[10], *ptr;
|
||||
|
||||
if (use_gfx_mode == true) {
|
||||
gfx_state.tg_fb_type = FB_GOP;
|
||||
if (gfx_state.tg_private == NULL) {
|
||||
(void) BS->LocateProtocol(&gop_guid, NULL,
|
||||
(void **)&gop);
|
||||
gfx_state.tg_private = gop;
|
||||
} else {
|
||||
gop = gfx_state.tg_private;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have FB but no GOP - it must be UGA.
|
||||
*/
|
||||
if (gop == NULL)
|
||||
gfx_state.tg_fb_type = FB_UGA;
|
||||
|
||||
if (efi_find_framebuffer(&efifb) == 0) {
|
||||
int roff, goff, boff;
|
||||
|
||||
gfx_state.tg_fb.fb_addr = efifb.fb_addr;
|
||||
gfx_state.tg_fb.fb_size = efifb.fb_size;
|
||||
gfx_state.tg_fb.fb_height = efifb.fb_height;
|
||||
gfx_state.tg_fb.fb_width = efifb.fb_width;
|
||||
gfx_state.tg_fb.fb_stride = efifb.fb_stride;
|
||||
gfx_state.tg_fb.fb_mask_red = efifb.fb_mask_red;
|
||||
gfx_state.tg_fb.fb_mask_green = efifb.fb_mask_green;
|
||||
gfx_state.tg_fb.fb_mask_blue = efifb.fb_mask_blue;
|
||||
gfx_state.tg_fb.fb_mask_reserved =
|
||||
efifb.fb_mask_reserved;
|
||||
roff = ffs(efifb.fb_mask_red) - 1;
|
||||
goff = ffs(efifb.fb_mask_green) - 1;
|
||||
boff = ffs(efifb.fb_mask_blue) - 1;
|
||||
|
||||
(void) generate_cons_palette(cmap, COLOR_FORMAT_RGB,
|
||||
efifb.fb_mask_red >> roff, roff,
|
||||
efifb.fb_mask_green >> goff, goff,
|
||||
efifb.fb_mask_blue >> boff, boff);
|
||||
gfx_state.tg_fb.fb_bpp = fls(
|
||||
efifb.fb_mask_red | efifb.fb_mask_green |
|
||||
efifb.fb_mask_blue | efifb.fb_mask_reserved);
|
||||
}
|
||||
} else {
|
||||
gfx_state.tg_fb_type = FB_TEXT;
|
||||
}
|
||||
|
||||
status = conout->QueryMode(conout, conout->Mode->Mode, &cols, &rows);
|
||||
if (EFI_ERROR(status) || cols * rows == 0) {
|
||||
cols = 80;
|
||||
rows = 24;
|
||||
cols = TEXT_COLS;
|
||||
rows = TEXT_ROWS;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -853,20 +951,74 @@ efi_cons_update_mode(void)
|
||||
*/
|
||||
mode = parse_uefi_con_out();
|
||||
if ((mode & (RB_SERIAL | RB_MULTIPLE)) == 0) {
|
||||
if (buffer != NULL) {
|
||||
if (tp.tp_row == rows && tp.tp_col == cols)
|
||||
return (true);
|
||||
free(buffer);
|
||||
conout->EnableCursor(conout, FALSE);
|
||||
gfx_state.tg_cursor_visible = false;
|
||||
|
||||
if (gfx_state.tg_fb_type == FB_TEXT) {
|
||||
|
||||
gfx_state.tg_functions = &tf;
|
||||
/* ensure the following are not set for text mode */
|
||||
unsetenv("screen.height");
|
||||
unsetenv("screen.width");
|
||||
unsetenv("screen.depth");
|
||||
} else {
|
||||
teken_init(&teken, &tf, NULL);
|
||||
uint32_t fb_height, fb_width;
|
||||
|
||||
fb_height = gfx_state.tg_fb.fb_height;
|
||||
fb_width = gfx_state.tg_fb.fb_width;
|
||||
|
||||
/*
|
||||
* setup_font() can adjust terminal size.
|
||||
* Note, we assume 80x24 terminal first, this is
|
||||
* because the font selection will attempt to achieve
|
||||
* at least this terminal dimension and we do not
|
||||
* end up with too small font.
|
||||
*/
|
||||
gfx_state.tg_tp.tp_row = TEXT_ROWS;
|
||||
gfx_state.tg_tp.tp_col = TEXT_COLS;
|
||||
setup_font(&gfx_state, fb_height, fb_width);
|
||||
rows = gfx_state.tg_tp.tp_row;
|
||||
cols = gfx_state.tg_tp.tp_col;
|
||||
/* Point of origin in pixels. */
|
||||
gfx_state.tg_origin.tp_row = (fb_height -
|
||||
(rows * gfx_state.tg_font.vf_height)) / 2;
|
||||
gfx_state.tg_origin.tp_col = (fb_width -
|
||||
(cols * gfx_state.tg_font.vf_width)) / 2;
|
||||
|
||||
/* UEFI gop has depth 32. */
|
||||
gfx_state.tg_glyph_size = gfx_state.tg_font.vf_height *
|
||||
gfx_state.tg_font.vf_width * 4;
|
||||
free(gfx_state.tg_glyph);
|
||||
gfx_state.tg_glyph = malloc(gfx_state.tg_glyph_size);
|
||||
if (gfx_state.tg_glyph == NULL)
|
||||
return (false);
|
||||
|
||||
gfx_state.tg_functions = &tfx;
|
||||
snprintf(env, sizeof (env), "%d", fb_height);
|
||||
env_setenv("screen.height", EV_VOLATILE | EV_NOHOOK,
|
||||
env, env_noset, env_screen_nounset);
|
||||
snprintf(env, sizeof (env), "%d", fb_width);
|
||||
env_setenv("screen.width", EV_VOLATILE | EV_NOHOOK,
|
||||
env, env_noset, env_screen_nounset);
|
||||
snprintf(env, sizeof (env), "%d",
|
||||
gfx_state.tg_fb.fb_bpp);
|
||||
env_setenv("screen.depth", EV_VOLATILE | EV_NOHOOK,
|
||||
env, env_noset, env_screen_nounset);
|
||||
}
|
||||
|
||||
tp.tp_row = rows;
|
||||
tp.tp_col = cols;
|
||||
buffer = malloc(rows * cols * sizeof(*buffer));
|
||||
if (buffer != NULL) {
|
||||
teken_set_winsize(&teken, &tp);
|
||||
a = teken_get_defattr(&teken);
|
||||
/* Record our terminal screen size. */
|
||||
gfx_state.tg_tp.tp_row = rows;
|
||||
gfx_state.tg_tp.tp_col = cols;
|
||||
|
||||
teken_init(&gfx_state.tg_teken, gfx_state.tg_functions,
|
||||
&gfx_state);
|
||||
|
||||
free(screen_buffer);
|
||||
screen_buffer = malloc(rows * cols * sizeof(*screen_buffer));
|
||||
if (screen_buffer != NULL) {
|
||||
teken_set_winsize(&gfx_state.tg_teken,
|
||||
&gfx_state.tg_tp);
|
||||
a = teken_get_defattr(&gfx_state.tg_teken);
|
||||
attr = *a;
|
||||
|
||||
/*
|
||||
@ -880,7 +1032,7 @@ efi_cons_update_mode(void)
|
||||
ptr = getenv("teken.bg_color");
|
||||
attr.ta_bgcolor = strtol(ptr, NULL, 10);
|
||||
|
||||
teken_set_defattr(&teken, &attr);
|
||||
teken_set_defattr(&gfx_state.tg_teken, &attr);
|
||||
} else {
|
||||
snprintf(env, sizeof(env), "%d",
|
||||
attr.ta_fgcolor);
|
||||
@ -891,18 +1043,12 @@ efi_cons_update_mode(void)
|
||||
env_setenv("teken.bg_color", EV_VOLATILE, env,
|
||||
efi_set_colors, env_nounset);
|
||||
}
|
||||
|
||||
for (int row = 0; row < rows; row++) {
|
||||
for (int col = 0; col < cols; col++) {
|
||||
buffer[col + row * tp.tp_col].c = ' ';
|
||||
buffer[col + row * tp.tp_col].a = attr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (screen_buffer == NULL) {
|
||||
conout->EnableCursor(conout, TRUE);
|
||||
#ifdef TERM_EMU
|
||||
if (buffer == NULL) {
|
||||
conout->SetAttribute(conout, EFI_TEXT_ATTR(DEFAULT_FGCOLOR,
|
||||
DEFAULT_BGCOLOR));
|
||||
end_term();
|
||||
@ -910,8 +1056,23 @@ efi_cons_update_mode(void)
|
||||
curs_move(&curx, &cury, curx, cury);
|
||||
fg_c = DEFAULT_FGCOLOR;
|
||||
bg_c = DEFAULT_BGCOLOR;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
/* Improve visibility */
|
||||
if (attr.ta_bgcolor == TC_WHITE)
|
||||
attr.ta_bgcolor |= TC_LIGHT;
|
||||
teken_set_defattr(&gfx_state.tg_teken, &attr);
|
||||
|
||||
/* Draw frame around terminal area. */
|
||||
cons_draw_frame(&attr);
|
||||
/*
|
||||
* Erase display, this will also fill our screen
|
||||
* buffer.
|
||||
*/
|
||||
teken_input(&gfx_state.tg_teken, "\e[2J", 4);
|
||||
gfx_state.tg_functions->tf_param(&gfx_state,
|
||||
TP_SHOWCURSOR, 1);
|
||||
}
|
||||
|
||||
snprintf(env, sizeof (env), "%u", (unsigned)rows);
|
||||
setenv("LINES", env, 1);
|
||||
@ -926,8 +1087,13 @@ efi_cons_init(int arg)
|
||||
{
|
||||
EFI_STATUS status;
|
||||
|
||||
conout->EnableCursor(conout, TRUE);
|
||||
if (efi_cons_update_mode())
|
||||
if (efi_started)
|
||||
return (0);
|
||||
|
||||
efi_started = true;
|
||||
|
||||
gfx_framework_init();
|
||||
if (cons_update_mode(gfx_state.tg_fb_type != FB_TEXT))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
@ -1035,12 +1201,12 @@ efi_cons_putchar(int c)
|
||||
* Don't use Teken when we're doing pure serial, or a multiple console
|
||||
* with video "primary" because that's also serial.
|
||||
*/
|
||||
if ((mode & (RB_SERIAL | RB_MULTIPLE)) != 0 || buffer == NULL) {
|
||||
if ((mode & (RB_SERIAL | RB_MULTIPLE)) != 0 || screen_buffer == NULL) {
|
||||
input_byte(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
teken_input(&teken, &ch, sizeof (ch));
|
||||
teken_input(&gfx_state.tg_teken, &ch, sizeof (ch));
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -22,7 +22,9 @@ SRCS= autoload.c \
|
||||
framebuffer.c \
|
||||
main.c \
|
||||
self_reloc.c \
|
||||
vers.c
|
||||
vers.c \
|
||||
gfx_fb.c \
|
||||
8x16.c
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../loader
|
||||
.if ${MK_LOADER_ZFS} != "no"
|
||||
@ -33,6 +35,11 @@ CFLAGS+= -DEFI_ZFS_BOOT
|
||||
HAVE_ZFS= yes
|
||||
.endif
|
||||
|
||||
CFLAGS.gfx_fb.c += -I$(SRCTOP)/sys/teken
|
||||
CFLAGS.gfx_fb.c += -I${SRCTOP}/sys/cddl/contrib/opensolaris/common/lz4
|
||||
CFLAGS.gfx_fb.c += -I${SRCTOP}/contrib/pnglite
|
||||
CFLAGS.gfx_fb.c += -DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib
|
||||
|
||||
# We implement a slightly non-standard %S in that it always takes a
|
||||
# CHAR16 that's common in UEFI-land instead of a wchar_t. This only
|
||||
# seems to matter on arm64 where wchar_t defaults to an int instead
|
||||
@ -74,6 +81,11 @@ VERSION_FILE= ${.CURDIR}/../loader/version
|
||||
# Always add MI sources
|
||||
.include "${BOOTSRC}/loader.mk"
|
||||
|
||||
CLEANFILES+= 8x16.c
|
||||
|
||||
8x16.c: ${SRCTOP}/contrib/terminus/ter-u16v.bdf
|
||||
vtfontcvt -f compressed-source -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
FILES+= ${LOADER}.efi
|
||||
FILESMODE_${LOADER}.efi= ${BINMODE}
|
||||
|
||||
|
@ -447,7 +447,7 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
|
||||
*/
|
||||
uint32_t mdt[] = {
|
||||
MODINFOMD_SSYM, MODINFOMD_ESYM, MODINFOMD_KERNEND,
|
||||
MODINFOMD_ENVP,
|
||||
MODINFOMD_ENVP, MODINFOMD_FONT,
|
||||
#if defined(LOADER_FDT_SUPPORT)
|
||||
MODINFOMD_DTBP
|
||||
#endif
|
||||
@ -480,6 +480,11 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
|
||||
/* Pad to a page boundary. */
|
||||
addr = roundup(addr, PAGE_SIZE);
|
||||
|
||||
addr = build_font_module(addr);
|
||||
|
||||
/* Pad to a page boundary. */
|
||||
addr = roundup(addr, PAGE_SIZE);
|
||||
|
||||
/* Copy our environment. */
|
||||
envp = addr;
|
||||
addr = bi_copyenv(addr);
|
||||
@ -503,17 +508,17 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
|
||||
if (kfp == NULL)
|
||||
panic("can't find kernel file");
|
||||
kernend = 0; /* fill it in later */
|
||||
file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
|
||||
file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
|
||||
file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof(howto), &howto);
|
||||
file_addmetadata(kfp, MODINFOMD_ENVP, sizeof(envp), &envp);
|
||||
#if defined(LOADER_FDT_SUPPORT)
|
||||
if (dtb_size)
|
||||
file_addmetadata(kfp, MODINFOMD_DTBP, sizeof dtbp, &dtbp);
|
||||
file_addmetadata(kfp, MODINFOMD_DTBP, sizeof(dtbp), &dtbp);
|
||||
else
|
||||
printf("WARNING! Trying to fire up the kernel, but no "
|
||||
"device tree blob found!\n");
|
||||
#endif
|
||||
file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
|
||||
file_addmetadata(kfp, MODINFOMD_FW_HANDLE, sizeof ST, &ST);
|
||||
file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof(kernend), &kernend);
|
||||
file_addmetadata(kfp, MODINFOMD_FW_HANDLE, sizeof(ST), &ST);
|
||||
#ifdef LOADER_GELI_SUPPORT
|
||||
geli_export_key_metadata(kfp);
|
||||
#endif
|
||||
|
@ -40,9 +40,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <efipciio.h>
|
||||
#include <machine/metadata.h>
|
||||
|
||||
#include "bootstrap.h"
|
||||
#include "framebuffer.h"
|
||||
|
||||
static EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
static EFI_GUID pciio_guid = EFI_PCI_IO_PROTOCOL_GUID;
|
||||
static EFI_GUID uga_guid = EFI_UGA_DRAW_PROTOCOL_GUID;
|
||||
|
||||
@ -586,7 +587,7 @@ gop_autoresize(EFI_GRAPHICS_OUTPUT *gop)
|
||||
mode, EFI_ERROR_CODE(status));
|
||||
return (CMD_ERROR);
|
||||
}
|
||||
(void) efi_cons_update_mode();
|
||||
(void) cons_update_mode(true);
|
||||
}
|
||||
return (CMD_OK);
|
||||
}
|
||||
@ -611,7 +612,7 @@ text_autoresize()
|
||||
}
|
||||
if (max_dim > 0)
|
||||
conout->SetMode(conout, best_mode);
|
||||
(void) efi_cons_update_mode();
|
||||
(void) cons_update_mode(true);
|
||||
return (CMD_OK);
|
||||
}
|
||||
|
||||
@ -699,8 +700,10 @@ command_gop(int argc, char *argv[])
|
||||
argv[0], mode, EFI_ERROR_CODE(status));
|
||||
return (CMD_ERROR);
|
||||
}
|
||||
(void) efi_cons_update_mode();
|
||||
} else if (!strcmp(argv[1], "get")) {
|
||||
(void) cons_update_mode(true);
|
||||
} else if (strcmp(argv[1], "off") == 0) {
|
||||
(void) cons_update_mode(false);
|
||||
} else if (strcmp(argv[1], "get") == 0) {
|
||||
if (argc != 2)
|
||||
goto usage;
|
||||
efifb_from_gop(&efifb, gop->Mode, gop->Mode->Info);
|
||||
@ -728,7 +731,7 @@ command_gop(int argc, char *argv[])
|
||||
|
||||
usage:
|
||||
snprintf(command_errbuf, sizeof(command_errbuf),
|
||||
"usage: %s [list | get | set <mode>]", argv[0]);
|
||||
"usage: %s [list | get | set <mode> | off]", argv[0]);
|
||||
return (CMD_ERROR);
|
||||
}
|
||||
|
||||
|
@ -1155,6 +1155,7 @@ main(int argc, CHAR16 *argv[])
|
||||
!interactive_interrupt("Failed to find bootable partition"))
|
||||
return (EFI_NOT_FOUND);
|
||||
|
||||
autoload_font(false); /* Set up the font list for console. */
|
||||
efi_init_environment();
|
||||
|
||||
#if !defined(__arm__)
|
||||
@ -1354,7 +1355,7 @@ command_mode(int argc, char *argv[])
|
||||
printf("couldn't set mode %d\n", mode);
|
||||
return (CMD_ERROR);
|
||||
}
|
||||
(void) efi_cons_update_mode();
|
||||
(void) cons_update_mode(true);
|
||||
return (CMD_OK);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ CFLAGS+= -fPIC
|
||||
.endif
|
||||
|
||||
CFLAGS+= -I${FICLSRC} -I${FICLSRC}/${FICL_CPUARCH} -I${LDRSRC}
|
||||
CFLAGS+= -DBF_DICTSIZE=15000
|
||||
CFLAGS+= -DBF_DICTSIZE=30000
|
||||
|
||||
.if ${MK_LOADER_VERIEXEC} != "no"
|
||||
CFLAGS+= -DLOADER_VERIEXEC -I${SRCTOP}/lib/libsecureboot/h
|
||||
|
@ -12,6 +12,8 @@ BASE_SRCS= dict.c ficl.c fileaccess.c float.c loader.c math64.c \
|
||||
SRCS= ${BASE_SRCS} sysdep.c softcore.c
|
||||
CLEANFILES+= softcore.c testmain testmain.o
|
||||
|
||||
CFLAGS.loader.c += -I${SRCTOP}/sys/teken
|
||||
CFLAGS.loader.c += -I${SRCTOP}/contrib/pnglite
|
||||
.ifmake testmain
|
||||
CFLAGS= -DTESTMAIN -D_TESTMAIN
|
||||
CFLAGS+= -I${FICLSRC} -I${FICLSRC}/${FICL_CPUARCH} -I${LDRSRC}
|
||||
|
@ -46,6 +46,8 @@
|
||||
#include "bootstrap.h"
|
||||
#include <string.h>
|
||||
#include <uuid.h>
|
||||
#include <gfx_fb.h>
|
||||
#include <pnglite.h>
|
||||
#include "ficl.h"
|
||||
|
||||
/* FreeBSD's loader interaction words and extras
|
||||
@ -65,6 +67,182 @@
|
||||
* .# ( value -- )
|
||||
*/
|
||||
|
||||
#ifndef TESTMAIN
|
||||
/* ( flags x1 y1 x2 y2 -- flag ) */
|
||||
void
|
||||
ficl_term_putimage(FICL_VM *pVM)
|
||||
{
|
||||
char *namep, *name;
|
||||
int names;
|
||||
unsigned long ret = FICL_FALSE;
|
||||
uint32_t x1, y1, x2, y2, f;
|
||||
png_t png;
|
||||
int error;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 7, 1);
|
||||
#endif
|
||||
names = stackPopINT(pVM->pStack);
|
||||
namep = (char *) stackPopPtr(pVM->pStack);
|
||||
y2 = stackPopINT(pVM->pStack);
|
||||
x2 = stackPopINT(pVM->pStack);
|
||||
y1 = stackPopINT(pVM->pStack);
|
||||
x1 = stackPopINT(pVM->pStack);
|
||||
f = stackPopINT(pVM->pStack);
|
||||
|
||||
x1 = gfx_state.tg_origin.tp_col + x1 * gfx_state.tg_font.vf_width;
|
||||
y1 = gfx_state.tg_origin.tp_row + y1 * gfx_state.tg_font.vf_height;
|
||||
if (x2 != 0) {
|
||||
x2 = gfx_state.tg_origin.tp_col +
|
||||
x2 * gfx_state.tg_font.vf_width;
|
||||
}
|
||||
if (y2 != 0) {
|
||||
y2 = gfx_state.tg_origin.tp_row +
|
||||
y2 * gfx_state.tg_font.vf_height;
|
||||
}
|
||||
|
||||
name = ficlMalloc(names + 1);
|
||||
if (!name)
|
||||
vmThrowErr(pVM, "Error: out of memory");
|
||||
(void) strncpy(name, namep, names);
|
||||
name[names] = '\0';
|
||||
|
||||
if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
|
||||
if (f & FL_PUTIMAGE_DEBUG)
|
||||
printf("%s\n", png_error_string(error));
|
||||
} else {
|
||||
if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
|
||||
ret = FICL_TRUE; /* success */
|
||||
(void) png_close(&png);
|
||||
}
|
||||
ficlFree(name);
|
||||
stackPushUNS(pVM->pStack, ret);
|
||||
}
|
||||
|
||||
/* ( flags x1 y1 x2 y2 -- flag ) */
|
||||
void
|
||||
ficl_fb_putimage(FICL_VM *pVM)
|
||||
{
|
||||
char *namep, *name;
|
||||
int names;
|
||||
unsigned long ret = FICL_FALSE;
|
||||
uint32_t x1, y1, x2, y2, f;
|
||||
png_t png;
|
||||
int error;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 7, 1);
|
||||
#endif
|
||||
names = stackPopINT(pVM->pStack);
|
||||
namep = (char *) stackPopPtr(pVM->pStack);
|
||||
y2 = stackPopINT(pVM->pStack);
|
||||
x2 = stackPopINT(pVM->pStack);
|
||||
y1 = stackPopINT(pVM->pStack);
|
||||
x1 = stackPopINT(pVM->pStack);
|
||||
f = stackPopINT(pVM->pStack);
|
||||
|
||||
name = ficlMalloc(names + 1);
|
||||
if (!name)
|
||||
vmThrowErr(pVM, "Error: out of memory");
|
||||
(void) strncpy(name, namep, names);
|
||||
name[names] = '\0';
|
||||
|
||||
if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
|
||||
if (f & FL_PUTIMAGE_DEBUG)
|
||||
printf("%s\n", png_error_string(error));
|
||||
} else {
|
||||
if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
|
||||
ret = FICL_TRUE; /* success */
|
||||
(void) png_close(&png);
|
||||
}
|
||||
ficlFree(name);
|
||||
stackPushUNS(pVM->pStack, ret);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_fb_setpixel(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x, y;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 2, 0);
|
||||
#endif
|
||||
|
||||
y = stackPopUNS(pVM->pStack);
|
||||
x = stackPopUNS(pVM->pStack);
|
||||
gfx_fb_setpixel(x, y);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_fb_line(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x0, y0, x1, y1, wd;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 5, 0);
|
||||
#endif
|
||||
|
||||
wd = stackPopUNS(pVM->pStack);
|
||||
y1 = stackPopUNS(pVM->pStack);
|
||||
x1 = stackPopUNS(pVM->pStack);
|
||||
y0 = stackPopUNS(pVM->pStack);
|
||||
x0 = stackPopUNS(pVM->pStack);
|
||||
gfx_fb_line(x0, y0, x1, y1, wd);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_fb_bezier(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x0, y0, x1, y1, x2, y2, width;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 7, 0);
|
||||
#endif
|
||||
|
||||
width = stackPopUNS(pVM->pStack);
|
||||
y2 = stackPopUNS(pVM->pStack);
|
||||
x2 = stackPopUNS(pVM->pStack);
|
||||
y1 = stackPopUNS(pVM->pStack);
|
||||
x1 = stackPopUNS(pVM->pStack);
|
||||
y0 = stackPopUNS(pVM->pStack);
|
||||
x0 = stackPopUNS(pVM->pStack);
|
||||
gfx_fb_bezier(x0, y0, x1, y1, x2, y2, width);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_fb_drawrect(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x1, x2, y1, y2, fill;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 5, 0);
|
||||
#endif
|
||||
|
||||
fill = stackPopUNS(pVM->pStack);
|
||||
y2 = stackPopUNS(pVM->pStack);
|
||||
x2 = stackPopUNS(pVM->pStack);
|
||||
y1 = stackPopUNS(pVM->pStack);
|
||||
x1 = stackPopUNS(pVM->pStack);
|
||||
gfx_fb_drawrect(x1, y1, x2, y2, fill);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_term_drawrect(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x1, x2, y1, y2;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 4, 0);
|
||||
#endif
|
||||
|
||||
y2 = stackPopUNS(pVM->pStack);
|
||||
x2 = stackPopUNS(pVM->pStack);
|
||||
y1 = stackPopUNS(pVM->pStack);
|
||||
x1 = stackPopUNS(pVM->pStack);
|
||||
gfx_term_drawrect(x1, y1, x2, y2);
|
||||
}
|
||||
#endif /* TESTMAIN */
|
||||
|
||||
void
|
||||
ficlSetenv(FICL_VM *pVM)
|
||||
{
|
||||
@ -867,6 +1045,13 @@ void ficlCompilePlatform(FICL_SYSTEM *pSys)
|
||||
dictAppendWord(dp, "uuid-from-string", ficlUuidFromString, FW_DEFAULT);
|
||||
dictAppendWord(dp, "uuid-to-string", ficlUuidToString, FW_DEFAULT);
|
||||
#ifndef TESTMAIN
|
||||
dictAppendWord(dp, "fb-setpixel", ficl_fb_setpixel, FW_DEFAULT);
|
||||
dictAppendWord(dp, "fb-line", ficl_fb_line, FW_DEFAULT);
|
||||
dictAppendWord(dp, "fb-bezier", ficl_fb_bezier, FW_DEFAULT);
|
||||
dictAppendWord(dp, "fb-drawrect", ficl_fb_drawrect, FW_DEFAULT);
|
||||
dictAppendWord(dp, "fb-putimage", ficl_fb_putimage, FW_DEFAULT);
|
||||
dictAppendWord(dp, "term-drawrect", ficl_term_drawrect, FW_DEFAULT);
|
||||
dictAppendWord(dp, "term-putimage", ficl_term_putimage, FW_DEFAULT);
|
||||
dictAppendWord(dp, "isvirtualized?",ficlIsvirtualizedQ, FW_DEFAULT);
|
||||
#endif
|
||||
|
||||
|
66
stand/fonts/INDEX.fonts
Normal file
66
stand/fonts/INDEX.fonts
Normal file
@ -0,0 +1,66 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
# database for vidfont(8)
|
||||
#
|
||||
# Format <file>:<lang>:<description>
|
||||
#
|
||||
# lang: ar bg cs da de el en es fi fr hr hu hy is it iw ja ko nl no pl
|
||||
# pt ro ru sh sk sl sv tr uk zh
|
||||
# lang: lang,lang
|
||||
#
|
||||
# Example:
|
||||
# terminus-b32.fnt:de:Terminus Schriftart
|
||||
# terminus-b32.fnt:en:Terminus font
|
||||
#
|
||||
# If lang is empty use 'en' (us-english) as default.
|
||||
#
|
||||
# See also setlocale(3),
|
||||
# /usr/share/locale, /usr/X11/lib/X11/locale/locale.alias
|
||||
#
|
||||
################################
|
||||
# Language support: MENU, FONT
|
||||
#
|
||||
MENU:en:Choose your terminal font
|
||||
MENU:da:Vælg skrifttypen til din terminal
|
||||
MENU:de:Wählen Sie Ihre Schrift
|
||||
MENU:fr:Choisissez votre fonte écran
|
||||
|
||||
#
|
||||
# The font definition for "en" is the fall-back font for
|
||||
# all languages.
|
||||
# Add language specific font definitions only where required!
|
||||
#
|
||||
FONT:en:8x16v.fnt
|
||||
#
|
||||
|
||||
6x12.fnt:en:Terminus BSD Console, size 12
|
||||
6x12.fnt:da:Terminus BSD-konsol, størrelse 12
|
||||
6x12.fnt:de:Terminus BSD Console, Größe 12
|
||||
8x14.fnt:en:Terminus BSD Console, size 14
|
||||
8x14.fnt:da:Terminus BSD-konsol, størrelse 14
|
||||
8x14.fnt:de:Terminus BSD Console, Größe 14
|
||||
8x16.fnt:en:Terminus BSD Console, size 16
|
||||
8x16.fnt:da:Terminus BSD-konsol, størrelse 16
|
||||
8x16.fnt:de:Terminus BSD Console, Größe 16
|
||||
10x18.fnt:en:Terminus BSD Console, size 18
|
||||
10x18.fnt:da:Terminus BSD-konsol, størrelse 18
|
||||
10x18.fnt:de:Terminus BSD Console, Größe 18
|
||||
10x20.fnt:en:Terminus BSD Console, size 20
|
||||
10x20.fnt:da:Terminus BSD-konsol, størrelse 20
|
||||
10x20.fnt:de:Terminus BSD Console, Größe 20
|
||||
11x22.fnt:en:Terminus BSD Console, size 22
|
||||
11x22.fnt:da:Terminus BSD-konsol, størrelse 22
|
||||
11x22.fnt:de:Terminus BSD Console, Größe 22
|
||||
12x24.fnt:en:Terminus BSD Console, size 24
|
||||
12x24.fnt:da:Terminus BSD-konsol, størrelse 24
|
||||
12x24.fnt:de:Terminus BSD Console, Größe 24
|
||||
14x28.fnt:en:Terminus BSD Console, size 28
|
||||
14x28.fnt:da:Terminus BSD-konsol, størrelse 28
|
||||
14x28.fnt:de:Terminus BSD Console, Größe 28
|
||||
16x32.fnt:en:Terminus BSD Console, size 32
|
||||
16x32.fnt:da:Terminus BSD-konsol, størrelse 32
|
||||
16x32.fnt:de:Terminus BSD Console, Größe 32
|
||||
|
||||
# (fset 'langnew
|
||||
# "\M-}\C-p\C-k\C-y\C-m\C-y\M-}")
|
81
stand/fonts/Makefile
Normal file
81
stand/fonts/Makefile
Normal file
@ -0,0 +1,81 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <bsd.init.mk>
|
||||
|
||||
.PATH: ${SRCTOP}/contrib/terminus
|
||||
|
||||
FONTS= \
|
||||
6x12.fnt.gz \
|
||||
8x14.fnt.gz \
|
||||
8x14v.fnt.gz \
|
||||
8x16.fnt.gz \
|
||||
8x16v.fnt.gz \
|
||||
10x18.fnt.gz \
|
||||
10x20.fnt.gz \
|
||||
11x22.fnt.gz \
|
||||
12x24.fnt.gz \
|
||||
14x28.fnt.gz \
|
||||
16x32.fnt.gz \
|
||||
|
||||
FILES= ${FONTS} INDEX.fonts
|
||||
FILESDIR= /boot/fonts
|
||||
|
||||
CLEANFILES+= ${FONTS} ${FONTS:T:S/${COMPRESS_EXT}//g}
|
||||
|
||||
6x12.fnt.gz: 6x12.fnt
|
||||
${COMPRESS_CMD} ${.ALLSRC} > ${.TARGET}
|
||||
8x14.fnt.gz: 8x14.fnt
|
||||
${COMPRESS_CMD} ${.ALLSRC} > ${.TARGET}
|
||||
8x14v.fnt.gz: 8x14v.fnt
|
||||
${COMPRESS_CMD} ${.ALLSRC} > ${.TARGET}
|
||||
8x16.fnt.gz: 8x16.fnt
|
||||
${COMPRESS_CMD} ${.ALLSRC} > ${.TARGET}
|
||||
8x16v.fnt.gz: 8x16v.fnt
|
||||
${COMPRESS_CMD} ${.ALLSRC} > ${.TARGET}
|
||||
10x18.fnt.gz: 10x18.fnt
|
||||
${COMPRESS_CMD} ${.ALLSRC} > ${.TARGET}
|
||||
10x20.fnt.gz: 10x20.fnt
|
||||
${COMPRESS_CMD} ${.ALLSRC} > ${.TARGET}
|
||||
11x22.fnt.gz: 11x22.fnt
|
||||
${COMPRESS_CMD} ${.ALLSRC} > ${.TARGET}
|
||||
12x24.fnt.gz: 12x24.fnt
|
||||
${COMPRESS_CMD} ${.ALLSRC} > ${.TARGET}
|
||||
14x28.fnt.gz: 14x28.fnt
|
||||
${COMPRESS_CMD} ${.ALLSRC} > ${.TARGET}
|
||||
16x32.fnt.gz: 16x32.fnt
|
||||
${COMPRESS_CMD} ${.ALLSRC} > ${.TARGET}
|
||||
|
||||
6x12.fnt: ter-u12n.bdf ter-u12b.bdf
|
||||
vtfontcvt -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
8x14.fnt: ter-u14n.bdf ter-u14b.bdf
|
||||
vtfontcvt -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
8x14v.fnt: ter-u14v.bdf
|
||||
vtfontcvt -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
8x16.fnt: ter-u16n.bdf ter-u16b.bdf
|
||||
vtfontcvt -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
8x16v.fnt: ter-u16v.bdf
|
||||
vtfontcvt -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
10x18.fnt: ter-u18n.bdf ter-u18b.bdf
|
||||
vtfontcvt -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
10x20.fnt: ter-u20n.bdf ter-u20b.bdf
|
||||
vtfontcvt -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
11x22.fnt: ter-u22n.bdf ter-u22b.bdf
|
||||
vtfontcvt -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
12x24.fnt: ter-u24n.bdf ter-u24b.bdf
|
||||
vtfontcvt -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
14x28.fnt: ter-u28n.bdf ter-u28b.bdf
|
||||
vtfontcvt -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
16x32.fnt: ter-u32n.bdf ter-u32b.bdf
|
||||
vtfontcvt -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -82,6 +82,10 @@ variable logoY
|
||||
then
|
||||
;
|
||||
|
||||
: draw-beastie
|
||||
['] draw-beastie console-iterate
|
||||
;
|
||||
|
||||
also support-functions
|
||||
|
||||
: beastie-start ( -- ) \ starts the menu
|
||||
|
@ -34,6 +34,18 @@
|
||||
|
||||
: brand ( x y -- ) \ "FreeBSD" [wide] logo in B/W (7 rows x 42 columns)
|
||||
|
||||
framebuffer? if
|
||||
s" term-putimage" sfind if
|
||||
\ note, we use 0, 0 for image upper left as origin,
|
||||
\ and 0, 7 for lower right to preserve aspect ratio
|
||||
>r 0 0 0 0 7
|
||||
s" /boot/images/freebsd-brand-rev.png"
|
||||
r> execute if 2drop exit then
|
||||
else
|
||||
drop
|
||||
then
|
||||
then
|
||||
|
||||
s" ______ ____ _____ _____ " brand+
|
||||
s" | ____| | _ \ / ____| __ \ " brand+
|
||||
s" | |___ _ __ ___ ___ | |_) | (___ | | | |" brand+
|
||||
|
@ -72,3 +72,7 @@ variable brandY
|
||||
else drop then
|
||||
then
|
||||
;
|
||||
|
||||
: draw-brand
|
||||
['] draw-brand console-iterate
|
||||
;
|
||||
|
@ -28,7 +28,7 @@ marker task-color.4th
|
||||
|
||||
\ This function returns FALSE if the `loader_color' environment variable is set
|
||||
\ to NO, no, or 0. It returns TRUE if `loader_color' is set to any other value.
|
||||
\ If `loader_color' is unset, TRUE is returned (unless booting serial).
|
||||
\ If `loader_color' is unset, TRUE is returned.
|
||||
\
|
||||
: loader_color? ( -- t )
|
||||
|
||||
@ -44,12 +44,8 @@ marker task-color.4th
|
||||
FALSE exit
|
||||
then
|
||||
drop
|
||||
then
|
||||
drop
|
||||
\ It is enabled.
|
||||
TRUE
|
||||
else
|
||||
\ `loader_color' is unset.
|
||||
\ Default to using color unless serial boot is active.
|
||||
drop
|
||||
boot_serial? 0=
|
||||
then
|
||||
;
|
||||
|
@ -121,6 +121,20 @@ only forth definitions also frame-drawing
|
||||
;
|
||||
|
||||
: box ( w h x y -- ) \ Draw a box
|
||||
framebuffer? if
|
||||
s" term-drawrect" sfind if
|
||||
>R
|
||||
rot ( w x y h )
|
||||
over + >R ( w x y -- R: y+h )
|
||||
swap rot ( y x w -- R: y+h )
|
||||
over + >R ( y x -- R: y+h x+w )
|
||||
swap R> R> R> execute
|
||||
exit
|
||||
else
|
||||
drop
|
||||
then
|
||||
then
|
||||
\ Non-framebuffer version
|
||||
2dup 1+ 4 pick 1- -rot
|
||||
vline \ Draw left vert line
|
||||
2dup 1+ swap 5 pick + swap 4 pick 1- -rot
|
||||
|
@ -35,6 +35,18 @@
|
||||
|
||||
: logo ( x y -- ) \ color Orb mascot (15 rows x 30 columns)
|
||||
|
||||
framebuffer? if
|
||||
s" term-putimage" sfind if
|
||||
>r 2dup ( x y x y )
|
||||
>r 0 swap r> ( x y 0 x y )
|
||||
dup 0 swap 15 + ( x y 0 x y 0 y+15 )
|
||||
s" /boot/images/freebsd-logo-rev.png"
|
||||
r> execute if 2drop exit then
|
||||
else
|
||||
drop
|
||||
then
|
||||
then
|
||||
|
||||
s" @[31m``` @[31;1m`@[31m" logo+
|
||||
s" s` `.....---...@[31;1m....--.``` -/@[31m" logo+
|
||||
s" +o .--` @[31;1m/y:` +.@[31m" logo+
|
||||
|
@ -991,6 +991,24 @@ only forth definitions also menu-infrastructure
|
||||
menu-create
|
||||
;
|
||||
|
||||
: menu-box
|
||||
f_double ( default frame type )
|
||||
\ Interpret a custom frame type for the menu
|
||||
TRUE ( draw a box? default yes, but might be altered below )
|
||||
s" loader_menu_frame" getenv dup -1 = if ( 1 )
|
||||
drop \ no custom frame type
|
||||
else ( 1 ) 2dup s" single" compare-insensitive 0= if ( 2 )
|
||||
f_single ( see frames.4th )
|
||||
else ( 2 ) 2dup s" double" compare-insensitive 0= if ( 3 )
|
||||
f_double ( see frames.4th )
|
||||
else ( 3 ) s" none" compare-insensitive 0= if ( 4 )
|
||||
drop FALSE \ don't draw a box
|
||||
( 4 ) then ( 3 ) then ( 2 ) then ( 1 ) then
|
||||
if
|
||||
42 13 menuX @ 3 - menuY @ 1- box \ Draw frame (w,h,x,y)
|
||||
then
|
||||
;
|
||||
|
||||
\ This function initializes the menu. Call this from your `loader.rc' file
|
||||
\ before calling any other menu-related functions.
|
||||
\
|
||||
@ -1021,21 +1039,7 @@ only forth definitions also menu-infrastructure
|
||||
then
|
||||
menuX !
|
||||
|
||||
\ Interpret a custom frame type for the menu
|
||||
TRUE ( draw a box? default yes, but might be altered below )
|
||||
s" loader_menu_frame" getenv dup -1 = if ( 1 )
|
||||
drop \ no custom frame type
|
||||
else ( 1 ) 2dup s" single" compare-insensitive 0= if ( 2 )
|
||||
f_single ( see frames.4th )
|
||||
else ( 2 ) 2dup s" double" compare-insensitive 0= if ( 3 )
|
||||
f_double ( see frames.4th )
|
||||
else ( 3 ) s" none" compare-insensitive 0= if ( 4 )
|
||||
drop FALSE \ don't draw a box
|
||||
( 4 ) then ( 3 ) then ( 2 ) then ( 1 ) then
|
||||
if
|
||||
42 13 menuX @ 3 - menuY @ 1- box \ Draw frame (w,h,x,y)
|
||||
then
|
||||
|
||||
['] menu-box console-iterate
|
||||
0 25 at-xy \ Move cursor to the bottom for output
|
||||
;
|
||||
|
||||
|
@ -190,6 +190,25 @@ create last_module_option sizeof module.next allot 0 last_module_option !
|
||||
0 0
|
||||
;
|
||||
|
||||
: strspn { addr len addr1 len1 | paddr plen -- addr' len' }
|
||||
begin
|
||||
len
|
||||
while
|
||||
addr1 to paddr
|
||||
len1 to plen
|
||||
begin
|
||||
plen
|
||||
while
|
||||
addr c@ paddr c@ = if addr len exit then
|
||||
paddr 1+ to paddr
|
||||
plen 1- to plen
|
||||
repeat
|
||||
addr 1 + to addr
|
||||
len 1 - to len
|
||||
repeat
|
||||
0 0
|
||||
;
|
||||
|
||||
: s' \ same as s", allows " in the string
|
||||
[char] ' parse
|
||||
state @ if postpone sliteral then
|
||||
@ -201,6 +220,53 @@ create last_module_option sizeof module.next allot 0 last_module_option !
|
||||
|
||||
: getenv? getenv -1 = if false else drop true then ;
|
||||
|
||||
\ execute xt for each device listed in console variable.
|
||||
\ this allows us to have device specific output for logos, menu frames etc
|
||||
: console-iterate { xt | caddr clen taddr tlen -- }
|
||||
\ get current console and save it
|
||||
s" console" getenv
|
||||
['] strdup catch if 2drop exit then
|
||||
to clen to caddr
|
||||
|
||||
clen to tlen
|
||||
caddr to taddr
|
||||
begin
|
||||
tlen
|
||||
while
|
||||
taddr tlen s" , " strspn
|
||||
\ we need to handle 3 cases for addr len pairs on stack:
|
||||
\ addr len are 0 0 - there was no comma nor space
|
||||
\ addr len are x 0 - the first char is either comma or space
|
||||
\ addr len are x y.
|
||||
2dup + 0= if
|
||||
\ there was no comma nor space.
|
||||
2drop
|
||||
taddr tlen s" console" setenv
|
||||
xt execute
|
||||
0 to tlen
|
||||
else dup 0= if
|
||||
2drop
|
||||
else
|
||||
dup ( taddr' tlen' tlen' )
|
||||
tlen swap - dup
|
||||
0= if \ sequence of comma and space?
|
||||
drop
|
||||
else
|
||||
taddr swap s" console" setenv
|
||||
xt execute
|
||||
then
|
||||
to tlen
|
||||
to taddr
|
||||
then then
|
||||
tlen 0> if \ step over separator
|
||||
tlen 1- to tlen
|
||||
taddr 1+ to taddr
|
||||
then
|
||||
repeat
|
||||
caddr clen s" console" setenv \ restore console setup
|
||||
caddr free drop
|
||||
;
|
||||
|
||||
\ determine if a word appears in a string, case-insensitive
|
||||
: contains? ( addr1 len1 addr2 len2 -- 0 | -1 )
|
||||
2 pick 0= if 2drop 2drop true exit then
|
||||
@ -231,14 +297,23 @@ create last_module_option sizeof module.next allot 0 last_module_option !
|
||||
s" console" getenv dup -1 <> if
|
||||
s" comconsole" 2swap contains?
|
||||
else drop false then
|
||||
s" boot_serial" getenv dup -1 <> if
|
||||
swap drop 0>
|
||||
else drop false then
|
||||
or \ console contains comconsole ( or ) boot_serial
|
||||
s" boot_multicons" getenv dup -1 <> if
|
||||
swap drop 0>
|
||||
else drop false then
|
||||
or \ previous boolean ( or ) boot_multicons
|
||||
\ s" boot_serial" getenv dup -1 <> if
|
||||
\ swap drop 0>
|
||||
\ else drop false then
|
||||
\ or \ console contains comconsole ( or ) boot_serial
|
||||
\ s" boot_multicons" getenv dup -1 <> if
|
||||
\ swap drop 0>
|
||||
\ else drop false then
|
||||
\ or \ previous boolean ( or ) boot_multicons
|
||||
;
|
||||
|
||||
: framebuffer? ( -- t )
|
||||
s" console" getenv
|
||||
2dup s" efi" compare 0<> >r
|
||||
s" vidconsole" compare 0<> r> and if
|
||||
FALSE exit
|
||||
then
|
||||
s" screen.depth" getenv?
|
||||
;
|
||||
|
||||
\ Private definitions
|
||||
|
@ -9,7 +9,7 @@ SRCS= bio.c biosacpi.c biosdisk.c biosmem.c biospnp.c \
|
||||
comconsole.c devicename.c elf32_freebsd.c \
|
||||
elf64_freebsd.c multiboot.c multiboot_tramp.S relocater_tramp.S \
|
||||
i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.S \
|
||||
time.c vidconsole.c amd64_tramp.S spinconsole.c
|
||||
time.c vidconsole.c vbe.c amd64_tramp.S spinconsole.c
|
||||
.PATH: ${ZFSSRC}
|
||||
SRCS+= devicename_stubs.c
|
||||
CFLAGS+= -I${ZFSSRC}
|
||||
@ -29,8 +29,13 @@ CFLAGS+= -DDISK_DEBUG
|
||||
.endif
|
||||
|
||||
# terminal emulation
|
||||
CFLAGS.vidconsole.c+= -I${SRCTOP}/sys/teken
|
||||
.if ${BOOT_FRAMEBUFFER_MODE:Uno} == "yes"
|
||||
CFLAGS.vidconsole.c+= -DFRAMEBUFFER_MODE
|
||||
.endif
|
||||
CFLAGS.vidconsole.c+= -I${SRCTOP}/sys/teken -I${SRCTOP}/contrib/pnglite
|
||||
CFLAGS.teken.c+= -I${SRCTOP}/sys/teken
|
||||
CFLAGS.bootinfo.c+= -I${SRCTOP}/sys/teken -I${SRCTOP}/contrib/pnglite
|
||||
CFLAGS.vbe.c+= -I${SRCTOP}/sys/teken -I${SRCTOP}/contrib/pnglite
|
||||
|
||||
# XXX: make alloca() useable
|
||||
CFLAGS+= -Dalloca=__builtin_alloca
|
||||
|
@ -32,10 +32,21 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/boot.h>
|
||||
#include <sys/linker.h>
|
||||
#include <gfx_fb.h>
|
||||
#include "bootstrap.h"
|
||||
#include "libi386.h"
|
||||
#include "vbe.h"
|
||||
#include "btxv86.h"
|
||||
|
||||
void
|
||||
bi_load_vbe_data(struct preloaded_file *kfp)
|
||||
{
|
||||
if (vbe_available()) {
|
||||
file_addmetadata(kfp, MODINFOMD_VBE_FB,
|
||||
sizeof(gfx_state.tg_fb), &gfx_state.tg_fb);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
bi_getboothowto(char *kargs)
|
||||
{
|
||||
|
@ -205,6 +205,8 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
|
||||
/* pad to a page boundary */
|
||||
addr = roundup(addr, PAGE_SIZE);
|
||||
|
||||
addr = build_font_module(addr);
|
||||
|
||||
/* copy our environment */
|
||||
envp = addr;
|
||||
addr = bi_copyenv(addr);
|
||||
@ -225,6 +227,7 @@ bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t
|
||||
#ifdef LOADER_GELI_SUPPORT
|
||||
geli_export_key_metadata(kfp);
|
||||
#endif
|
||||
bi_load_vbe_data(kfp);
|
||||
|
||||
/* Figure out the size and location of the metadata */
|
||||
*modulep = addr;
|
||||
|
@ -227,6 +227,8 @@ bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep,
|
||||
/* pad to a page boundary */
|
||||
addr = roundup(addr, PAGE_SIZE);
|
||||
|
||||
addr = build_font_module(addr);
|
||||
|
||||
/* place the metadata before anything */
|
||||
module = *modulep = addr;
|
||||
|
||||
@ -245,6 +247,7 @@ bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep,
|
||||
#ifdef LOADER_GELI_SUPPORT
|
||||
geli_export_key_metadata(kfp);
|
||||
#endif
|
||||
bi_load_vbe_data(kfp);
|
||||
|
||||
size = bi_copymodules64(0);
|
||||
|
||||
|
@ -145,6 +145,7 @@ void biosacpi_detect(void);
|
||||
|
||||
int i386_autoload(void);
|
||||
|
||||
void bi_load_vbe_data(struct preloaded_file *kfp);
|
||||
int bi_getboothowto(char *kargs);
|
||||
void bi_setboothowto(int howto);
|
||||
vm_offset_t bi_copyenv(vm_offset_t addr);
|
||||
|
1226
stand/i386/libi386/vbe.c
Normal file
1226
stand/i386/libi386/vbe.c
Normal file
File diff suppressed because it is too large
Load Diff
163
stand/i386/libi386/vbe.h
Normal file
163
stand/i386/libi386/vbe.h
Normal file
@ -0,0 +1,163 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Default mode for VESA frame buffer.
|
||||
* This mode is selected when there is no EDID inormation and
|
||||
* mode is not provided by user.
|
||||
* To provide consistent look with UEFI GOP, we use 800x600 here,
|
||||
* and if this mode is not available, we fall back to text mode and
|
||||
* VESA disabled.
|
||||
*/
|
||||
|
||||
#define VBE_DEFAULT_MODE "800x600"
|
||||
|
||||
struct vbeinfoblock {
|
||||
char VbeSignature[4];
|
||||
uint16_t VbeVersion;
|
||||
uint32_t OemStringPtr;
|
||||
uint32_t Capabilities;
|
||||
#define VBE_CAP_DAC8 (1 << 0) /* Can switch DAC */
|
||||
#define VBE_CAP_NONVGA (1 << 1) /* Controller is not VGA comp. */
|
||||
#define VBE_CAP_SNOW (1 << 2) /* Set data during Vertical Reterace */
|
||||
uint32_t VideoModePtr;
|
||||
uint16_t TotalMemory;
|
||||
uint16_t OemSoftwareRev;
|
||||
uint32_t OemVendorNamePtr, OemProductNamePtr, OemProductRevPtr;
|
||||
/* data area, in total max 512 bytes for VBE 2.0 */
|
||||
uint8_t Reserved[222];
|
||||
uint8_t OemData[256];
|
||||
} __packed;
|
||||
|
||||
struct modeinfoblock {
|
||||
/* Mandatory information for all VBE revisions */
|
||||
uint16_t ModeAttributes;
|
||||
uint8_t WinAAttributes, WinBAttributes;
|
||||
uint16_t WinGranularity, WinSize, WinASegment, WinBSegment;
|
||||
uint32_t WinFuncPtr;
|
||||
uint16_t BytesPerScanLine;
|
||||
/* Mandatory information for VBE 1.2 and above */
|
||||
uint16_t XResolution, YResolution;
|
||||
uint8_t XCharSize, YCharSize, NumberOfPlanes, BitsPerPixel;
|
||||
uint8_t NumberOfBanks, MemoryModel, BankSize, NumberOfImagePages;
|
||||
uint8_t Reserved1;
|
||||
/* Direct Color fields
|
||||
(required for direct/6 and YUV/7 memory models) */
|
||||
uint8_t RedMaskSize, RedFieldPosition;
|
||||
uint8_t GreenMaskSize, GreenFieldPosition;
|
||||
uint8_t BlueMaskSize, BlueFieldPosition;
|
||||
uint8_t RsvdMaskSize, RsvdFieldPosition;
|
||||
uint8_t DirectColorModeInfo;
|
||||
/* Mandatory information for VBE 2.0 and above */
|
||||
uint32_t PhysBasePtr;
|
||||
uint32_t OffScreenMemOffset; /* reserved in VBE 3.0 and above */
|
||||
uint16_t OffScreenMemSize; /* reserved in VBE 3.0 and above */
|
||||
|
||||
/* Mandatory information for VBE 3.0 and above */
|
||||
uint16_t LinBytesPerScanLine;
|
||||
uint8_t BnkNumberOfImagePages;
|
||||
uint8_t LinNumberOfImagePages;
|
||||
uint8_t LinRedMaskSize, LinRedFieldPosition;
|
||||
uint8_t LinGreenMaskSize, LinGreenFieldPosition;
|
||||
uint8_t LinBlueMaskSize, LinBlueFieldPosition;
|
||||
uint8_t LinRsvdMaskSize, LinRsvdFieldPosition;
|
||||
uint32_t MaxPixelClock;
|
||||
/* + 1 will fix the size to 256 bytes */
|
||||
uint8_t Reserved4[189 + 1];
|
||||
} __packed;
|
||||
|
||||
struct crtciinfoblock {
|
||||
uint16_t HorizontalTotal;
|
||||
uint16_t HorizontalSyncStart;
|
||||
uint16_t HorizontalSyncEnd;
|
||||
uint16_t VerticalTotal;
|
||||
uint16_t VerticalSyncStart;
|
||||
uint16_t VerticalSyncEnd;
|
||||
uint8_t Flags;
|
||||
uint32_t PixelClock;
|
||||
uint16_t RefreshRate;
|
||||
uint8_t Reserved[40];
|
||||
} __packed;
|
||||
|
||||
struct paletteentry {
|
||||
uint8_t Blue;
|
||||
uint8_t Green;
|
||||
uint8_t Red;
|
||||
uint8_t Reserved;
|
||||
} __packed;
|
||||
|
||||
struct flatpanelinfo
|
||||
{
|
||||
uint16_t HorizontalSize;
|
||||
uint16_t VerticalSize;
|
||||
uint16_t PanelType;
|
||||
uint8_t RedBPP;
|
||||
uint8_t GreenBPP;
|
||||
uint8_t BlueBPP;
|
||||
uint8_t ReservedBPP;
|
||||
uint32_t ReservedOffScreenMemSize;
|
||||
uint32_t ReservedOffScreenMemPtr;
|
||||
|
||||
uint8_t Reserved[14];
|
||||
} __packed;
|
||||
|
||||
#define VBE_BASE_MODE (0x100) /* VBE 3.0 page 18 */
|
||||
#define VBE_VALID_MODE(a) ((a) >= VBE_BASE_MODE)
|
||||
#define VBE_ERROR(a) (((a) & 0xFF) != 0x4F || ((a) & 0xFF00) != 0)
|
||||
#define VBE_SUCCESS (0x004F)
|
||||
#define VBE_FAILED (0x014F)
|
||||
#define VBE_NOTSUP (0x024F)
|
||||
#define VBE_INVALID (0x034F)
|
||||
|
||||
#define VGA_TEXT_MODE (3) /* 80x25 text mode */
|
||||
#define TEXT_ROWS (25) /* VGATEXT rows */
|
||||
#define TEXT_COLS (80) /* VGATEXT columns */
|
||||
|
||||
extern struct paletteentry *pe8;
|
||||
extern int palette_format;
|
||||
|
||||
int vga_get_reg(int, int);
|
||||
int vga_get_atr(int, int);
|
||||
void vga_set_atr(int, int, int);
|
||||
void vga_set_indexed(int, int, int, uint8_t, uint8_t);
|
||||
int vga_get_indexed(int, int, int, uint8_t);
|
||||
int vga_get_crtc(int, int);
|
||||
void vga_set_crtc(int, int, int);
|
||||
int vga_get_seq(int, int);
|
||||
void vga_set_seq(int, int, int);
|
||||
int vga_get_grc(int, int);
|
||||
void vga_set_grc(int, int, int);
|
||||
|
||||
/* high-level VBE helpers, from vbe.c */
|
||||
void bios_set_text_mode(int);
|
||||
int biosvbe_palette_format(int *);
|
||||
void vbe_init(void);
|
||||
bool vbe_available(void);
|
||||
int vbe_default_mode(void);
|
||||
int vbe_set_mode(int);
|
||||
int vbe_get_mode(void);
|
||||
int vbe_set_palette(const struct paletteentry *, size_t);
|
||||
void vbe_modelist(int);
|
@ -31,12 +31,13 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stand.h>
|
||||
#include <sys/param.h>
|
||||
#include <bootstrap.h>
|
||||
#include <btxv86.h>
|
||||
#include <machine/psl.h>
|
||||
#include <machine/cpufunc.h>
|
||||
#include <gfx_fb.h>
|
||||
#include <teken.h>
|
||||
#include <stdbool.h>
|
||||
#include "vbe.h"
|
||||
|
||||
#include <dev/vt/hw/vga/vt_vga_reg.h>
|
||||
|
||||
@ -50,6 +51,7 @@ static int vidc_init(int arg);
|
||||
static void vidc_putchar(int c);
|
||||
static int vidc_getchar(void);
|
||||
static int vidc_ischar(void);
|
||||
static void cons_draw_frame(teken_attr_t *);
|
||||
|
||||
static int vidc_started;
|
||||
static uint16_t *vgatext;
|
||||
@ -72,30 +74,16 @@ static teken_funcs_t tf = {
|
||||
.tf_respond = vidc_cons_respond,
|
||||
};
|
||||
|
||||
teken_t teken;
|
||||
teken_pos_t tp;
|
||||
|
||||
struct text_pixel {
|
||||
teken_char_t c;
|
||||
teken_attr_t a;
|
||||
static teken_funcs_t tfx = {
|
||||
.tf_bell = vidc_cons_bell,
|
||||
.tf_cursor = gfx_fb_cursor,
|
||||
.tf_putchar = gfx_fb_putchar,
|
||||
.tf_fill = gfx_fb_fill,
|
||||
.tf_copy = gfx_fb_copy,
|
||||
.tf_param = gfx_fb_param,
|
||||
.tf_respond = vidc_cons_respond,
|
||||
};
|
||||
|
||||
static struct text_pixel *buffer;
|
||||
|
||||
#define NCOLORS 16
|
||||
|
||||
/*
|
||||
* Between console's palette and VGA's one:
|
||||
* - blue and red are swapped (1 <-> 4)
|
||||
* - yellow and cyan are swapped (3 <-> 6)
|
||||
*/
|
||||
static const int cons_to_vga_colors[NCOLORS] = {
|
||||
0, 4, 2, 6, 1, 5, 3, 7,
|
||||
8, 12, 10, 14, 9, 13, 11, 15
|
||||
};
|
||||
|
||||
#define TEXT_COLS 80
|
||||
#define TEXT_ROWS 25
|
||||
#define KEYBUFSZ 10
|
||||
|
||||
static uint8_t keybuf[KEYBUFSZ]; /* keybuf for extended codes */
|
||||
@ -111,60 +99,26 @@ struct console vidconsole = {
|
||||
.c_ready = vidc_ischar
|
||||
};
|
||||
|
||||
static int
|
||||
vga_get_reg(int reg, int index)
|
||||
/*
|
||||
* This function is used to mark a rectangular image area so the scrolling
|
||||
* will know we need to copy the data from there.
|
||||
*/
|
||||
void
|
||||
term_image_display(teken_gfx_t *state, const teken_rect_t *r)
|
||||
{
|
||||
return (inb(reg + index));
|
||||
}
|
||||
teken_pos_t p;
|
||||
int idx;
|
||||
|
||||
static int
|
||||
vga_get_atr(int reg, int i)
|
||||
{
|
||||
int ret;
|
||||
|
||||
(void) inb(reg + VGA_GEN_INPUT_STAT_1);
|
||||
outb(reg + VGA_AC_WRITE, i);
|
||||
ret = inb(reg + VGA_AC_READ);
|
||||
|
||||
(void) inb(reg + VGA_GEN_INPUT_STAT_1);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
vga_set_atr(int reg, int i, int v)
|
||||
{
|
||||
(void) inb(reg + VGA_GEN_INPUT_STAT_1);
|
||||
outb(reg + VGA_AC_WRITE, i);
|
||||
outb(reg + VGA_AC_WRITE, v);
|
||||
|
||||
(void) inb(reg + VGA_GEN_INPUT_STAT_1);
|
||||
}
|
||||
|
||||
static void
|
||||
vga_set_indexed(int reg, int indexreg, int datareg, uint8_t index, uint8_t val)
|
||||
{
|
||||
outb(reg + indexreg, index);
|
||||
outb(reg + datareg, val);
|
||||
}
|
||||
|
||||
static int
|
||||
vga_get_indexed(int reg, int indexreg, int datareg, uint8_t index)
|
||||
{
|
||||
outb(reg + indexreg, index);
|
||||
return (inb(reg + datareg));
|
||||
}
|
||||
|
||||
static int
|
||||
vga_get_crtc(int reg, int i)
|
||||
{
|
||||
return (vga_get_indexed(reg, VGA_CRTC_ADDRESS, VGA_CRTC_DATA, i));
|
||||
}
|
||||
|
||||
static void
|
||||
vga_set_crtc(int reg, int i, int v)
|
||||
{
|
||||
vga_set_indexed(reg, VGA_CRTC_ADDRESS, VGA_CRTC_DATA, i, v);
|
||||
for (p.tp_row = r->tr_begin.tp_row;
|
||||
p.tp_row < r->tr_end.tp_row; p.tp_row++) {
|
||||
for (p.tp_col = r->tr_begin.tp_col;
|
||||
p.tp_col < r->tr_end.tp_col; p.tp_col++) {
|
||||
idx = p.tp_col + p.tp_row * state->tg_tp.tp_col;
|
||||
if (idx >= state->tg_tp.tp_col * state->tg_tp.tp_row)
|
||||
return;
|
||||
screen_buffer[idx].a.ta_format |= TF_IMAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -353,9 +307,9 @@ vga_get_cp437(teken_char_t c)
|
||||
}
|
||||
|
||||
static void
|
||||
vidc_text_printchar(const teken_pos_t *p)
|
||||
vidc_text_printchar(teken_gfx_t *state, const teken_pos_t *p)
|
||||
{
|
||||
int i;
|
||||
int idx;
|
||||
uint8_t attr;
|
||||
struct text_pixel *px;
|
||||
teken_color_t fg, bg, tmp;
|
||||
@ -364,7 +318,8 @@ vidc_text_printchar(const teken_pos_t *p)
|
||||
uint8_t attr;
|
||||
} *addr;
|
||||
|
||||
px = buffer + p->tp_col + p->tp_row * tp.tp_col;
|
||||
idx = p->tp_col + p->tp_row * state->tg_tp.tp_col;
|
||||
px = &screen_buffer[idx];
|
||||
fg = teken_256to16(px->a.ta_fgcolor);
|
||||
bg = teken_256to16(px->a.ta_bgcolor);
|
||||
if (px->a.ta_format & TF_BOLD)
|
||||
@ -378,29 +333,34 @@ vidc_text_printchar(const teken_pos_t *p)
|
||||
bg = tmp;
|
||||
}
|
||||
|
||||
attr = (cons_to_vga_colors[bg & 0xf] << 4) |
|
||||
cons_to_vga_colors[fg & 0xf];
|
||||
addr = (struct cgatext *)vgatext + p->tp_col + p->tp_row * tp.tp_col;
|
||||
addr->ch = vga_get_cp437(px->c);
|
||||
addr->attr = attr;
|
||||
attr = (cmap[bg & 0xf] << 4) | cmap[fg & 0xf];
|
||||
addr = (struct cgatext *)vgatext;
|
||||
addr[idx].ch = vga_get_cp437(px->c);
|
||||
addr[idx].attr = attr;
|
||||
}
|
||||
|
||||
static void
|
||||
vidc_text_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c,
|
||||
vidc_text_putchar(void *s, const teken_pos_t *p, teken_char_t c,
|
||||
const teken_attr_t *a)
|
||||
{
|
||||
teken_gfx_t *state = s;
|
||||
int attr, idx;
|
||||
|
||||
idx = p->tp_col + p->tp_row * tp.tp_col;
|
||||
buffer[idx].c = c;
|
||||
buffer[idx].a = *a;
|
||||
vidc_text_printchar(p);
|
||||
idx = p->tp_col + p->tp_row * state->tg_tp.tp_col;
|
||||
if (idx >= state->tg_tp.tp_col * state->tg_tp.tp_row)
|
||||
return;
|
||||
|
||||
screen_buffer[idx].c = c;
|
||||
screen_buffer[idx].a = *a;
|
||||
|
||||
vidc_text_printchar(state, p);
|
||||
}
|
||||
|
||||
static void
|
||||
vidc_text_fill(void *s, const teken_rect_t *r, teken_char_t c,
|
||||
vidc_text_fill(void *arg, const teken_rect_t *r, teken_char_t c,
|
||||
const teken_attr_t *a)
|
||||
{
|
||||
teken_gfx_t *state = arg;
|
||||
teken_pos_t p;
|
||||
teken_unit_t row, col;
|
||||
|
||||
@ -410,29 +370,14 @@ vidc_text_fill(void *s, const teken_rect_t *r, teken_char_t c,
|
||||
p.tp_row++)
|
||||
for (p.tp_col = r->tr_begin.tp_col;
|
||||
p.tp_col < r->tr_end.tp_col; p.tp_col++)
|
||||
vidc_text_putchar(s, &p, c, a);
|
||||
vidc_text_putchar(state, &p, c, a);
|
||||
vidc_text_set_cursor(row, col, true);
|
||||
}
|
||||
|
||||
static bool
|
||||
vidc_same_pixel(struct text_pixel *px1, struct text_pixel *px2)
|
||||
{
|
||||
if (px1->c != px2->c)
|
||||
return (false);
|
||||
|
||||
if (px1->a.ta_format != px2->a.ta_format)
|
||||
return (false);
|
||||
if (px1->a.ta_fgcolor != px2->a.ta_fgcolor)
|
||||
return (false);
|
||||
if (px1->a.ta_bgcolor != px2->a.ta_bgcolor)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static void
|
||||
vidc_text_copy(void *ptr __unused, const teken_rect_t *r, const teken_pos_t *p)
|
||||
vidc_text_copy(void *ptr, const teken_rect_t *r, const teken_pos_t *p)
|
||||
{
|
||||
teken_gfx_t *state = ptr;
|
||||
int srow, drow;
|
||||
int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */
|
||||
teken_pos_t d, s;
|
||||
@ -453,18 +398,18 @@ vidc_text_copy(void *ptr __unused, const teken_rect_t *r, const teken_pos_t *p)
|
||||
for (y = 0; y < nrow; y++) {
|
||||
d.tp_row = p->tp_row + y;
|
||||
s.tp_row = r->tr_begin.tp_row + y;
|
||||
drow = d.tp_row * tp.tp_col;
|
||||
srow = s.tp_row * tp.tp_col;
|
||||
drow = d.tp_row * state->tg_tp.tp_col;
|
||||
srow = s.tp_row * state->tg_tp.tp_col;
|
||||
for (x = 0; x < ncol; x++) {
|
||||
d.tp_col = p->tp_col + x;
|
||||
s.tp_col = r->tr_begin.tp_col + x;
|
||||
|
||||
if (!vidc_same_pixel(
|
||||
&buffer[d.tp_col + drow],
|
||||
&buffer[s.tp_col + srow])) {
|
||||
buffer[d.tp_col + drow] =
|
||||
buffer[s.tp_col + srow];
|
||||
vidc_text_printchar(&d);
|
||||
if (!is_same_pixel(
|
||||
&screen_buffer[d.tp_col + drow],
|
||||
&screen_buffer[s.tp_col + srow])) {
|
||||
screen_buffer[d.tp_col + drow] =
|
||||
screen_buffer[s.tp_col + srow];
|
||||
vidc_text_printchar(state, &d);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -475,18 +420,18 @@ vidc_text_copy(void *ptr __unused, const teken_rect_t *r, const teken_pos_t *p)
|
||||
for (y = nrow - 1; y >= 0; y--) {
|
||||
d.tp_row = p->tp_row + y;
|
||||
s.tp_row = r->tr_begin.tp_row + y;
|
||||
drow = d.tp_row * tp.tp_col;
|
||||
srow = s.tp_row * tp.tp_col;
|
||||
drow = d.tp_row * state->tg_tp.tp_col;
|
||||
srow = s.tp_row * state->tg_tp.tp_col;
|
||||
for (x = 0; x < ncol; x++) {
|
||||
d.tp_col = p->tp_col + x;
|
||||
s.tp_col = r->tr_begin.tp_col + x;
|
||||
|
||||
if (!vidc_same_pixel(
|
||||
&buffer[d.tp_col + drow],
|
||||
&buffer[s.tp_col + srow])) {
|
||||
buffer[d.tp_col + drow] =
|
||||
buffer[s.tp_col + srow];
|
||||
vidc_text_printchar(&d);
|
||||
if (!is_same_pixel(
|
||||
&screen_buffer[d.tp_col + drow],
|
||||
&screen_buffer[s.tp_col + srow])) {
|
||||
screen_buffer[d.tp_col + drow] =
|
||||
screen_buffer[s.tp_col + srow];
|
||||
vidc_text_printchar(state, &d);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -495,18 +440,18 @@ vidc_text_copy(void *ptr __unused, const teken_rect_t *r, const teken_pos_t *p)
|
||||
for (y = nrow - 1; y >= 0; y--) {
|
||||
d.tp_row = p->tp_row + y;
|
||||
s.tp_row = r->tr_begin.tp_row + y;
|
||||
drow = d.tp_row * tp.tp_col;
|
||||
srow = s.tp_row * tp.tp_col;
|
||||
drow = d.tp_row * state->tg_tp.tp_col;
|
||||
srow = s.tp_row * state->tg_tp.tp_col;
|
||||
for (x = ncol - 1; x >= 0; x--) {
|
||||
d.tp_col = p->tp_col + x;
|
||||
s.tp_col = r->tr_begin.tp_col + x;
|
||||
|
||||
if (!vidc_same_pixel(
|
||||
&buffer[d.tp_col + drow],
|
||||
&buffer[s.tp_col + srow])) {
|
||||
buffer[d.tp_col + drow] =
|
||||
buffer[s.tp_col + srow];
|
||||
vidc_text_printchar(&d);
|
||||
if (!is_same_pixel(
|
||||
&screen_buffer[d.tp_col + drow],
|
||||
&screen_buffer[s.tp_col + srow])) {
|
||||
screen_buffer[d.tp_col + drow] =
|
||||
screen_buffer[s.tp_col + srow];
|
||||
vidc_text_printchar(state, &d);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -516,8 +461,9 @@ vidc_text_copy(void *ptr __unused, const teken_rect_t *r, const teken_pos_t *p)
|
||||
}
|
||||
|
||||
static void
|
||||
vidc_text_param(void *s __unused, int cmd, unsigned int value)
|
||||
vidc_text_param(void *arg, int cmd, unsigned int value)
|
||||
{
|
||||
teken_gfx_t *state = arg;
|
||||
teken_unit_t row, col;
|
||||
|
||||
switch (cmd) {
|
||||
@ -532,10 +478,13 @@ vidc_text_param(void *s __unused, int cmd, unsigned int value)
|
||||
/* FALLTHROUGH */
|
||||
case TP_SHOWCURSOR:
|
||||
vidc_text_get_cursor(&row, &col);
|
||||
if (value == 1)
|
||||
if (value != 0) {
|
||||
vidc_text_set_cursor(row, col, true);
|
||||
else
|
||||
state->tg_cursor_visible = true;
|
||||
} else {
|
||||
vidc_text_set_cursor(row, col, false);
|
||||
state->tg_cursor_visible = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Not yet implemented */
|
||||
@ -635,7 +584,7 @@ vidc_set_colors(struct env_var *ev, int flags, const void *value)
|
||||
evalue = value;
|
||||
}
|
||||
|
||||
ap = teken_get_defattr(&teken);
|
||||
ap = teken_get_defattr(&gfx_state.tg_teken);
|
||||
a = *ap;
|
||||
if (strcmp(ev->ev_name, "teken.fg_color") == 0) {
|
||||
/* is it already set? */
|
||||
@ -654,11 +603,381 @@ vidc_set_colors(struct env_var *ev, int flags, const void *value)
|
||||
if (a.ta_bgcolor == TC_WHITE)
|
||||
a.ta_bgcolor |= TC_LIGHT;
|
||||
|
||||
teken_set_defattr(&gfx_state.tg_teken, &a);
|
||||
cons_draw_frame(&a);
|
||||
env_setenv(ev->ev_name, flags | EV_NOHOOK, evalue, NULL, NULL);
|
||||
teken_set_defattr(&teken, &a);
|
||||
teken_input(&gfx_state.tg_teken, "\e[2J", 4);
|
||||
|
||||
return (CMD_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
env_screen_nounset(struct env_var *ev __unused)
|
||||
{
|
||||
if (gfx_state.tg_fb_type == FB_TEXT)
|
||||
return (0);
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
static int
|
||||
vidc_load_palette(uint32_t *cmap)
|
||||
{
|
||||
int i, roff, goff, boff, rc;
|
||||
|
||||
if (pe8 == NULL)
|
||||
pe8 = calloc(sizeof(*pe8), NCMAP);
|
||||
if (pe8 == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
/* Generate VGA colors */
|
||||
roff = ffs(gfx_state.tg_fb.fb_mask_red) - 1;
|
||||
goff = ffs(gfx_state.tg_fb.fb_mask_green) - 1;
|
||||
boff = ffs(gfx_state.tg_fb.fb_mask_blue) - 1;
|
||||
rc = generate_cons_palette((uint32_t *)pe8, COLOR_FORMAT_RGB,
|
||||
gfx_state.tg_fb.fb_mask_red >> roff, roff,
|
||||
gfx_state.tg_fb.fb_mask_green >> goff, goff,
|
||||
gfx_state.tg_fb.fb_mask_blue >> boff, boff);
|
||||
|
||||
if (rc == 0) {
|
||||
for (i = 0; i < NCMAP; i++) {
|
||||
int idx;
|
||||
|
||||
if (i < NCOLORS)
|
||||
idx = cons_to_vga_colors[i];
|
||||
else
|
||||
idx = i;
|
||||
|
||||
rc = vbe_set_palette(&pe8[i], idx);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static void
|
||||
cons_draw_frame(teken_attr_t *a)
|
||||
{
|
||||
teken_attr_t attr = *a;
|
||||
teken_color_t fg = a->ta_fgcolor;
|
||||
|
||||
attr.ta_fgcolor = attr.ta_bgcolor;
|
||||
teken_set_defattr(&gfx_state.tg_teken, &attr);
|
||||
|
||||
gfx_fb_drawrect(0, 0, gfx_state.tg_fb.fb_width,
|
||||
gfx_state.tg_origin.tp_row, 1);
|
||||
gfx_fb_drawrect(0,
|
||||
gfx_state.tg_fb.fb_height - gfx_state.tg_origin.tp_row - 1,
|
||||
gfx_state.tg_fb.fb_width, gfx_state.tg_fb.fb_height, 1);
|
||||
gfx_fb_drawrect(0, gfx_state.tg_origin.tp_row,
|
||||
gfx_state.tg_origin.tp_col,
|
||||
gfx_state.tg_fb.fb_height - gfx_state.tg_origin.tp_row - 1, 1);
|
||||
gfx_fb_drawrect(
|
||||
gfx_state.tg_fb.fb_width - gfx_state.tg_origin.tp_col - 1,
|
||||
gfx_state.tg_origin.tp_row, gfx_state.tg_fb.fb_width,
|
||||
gfx_state.tg_fb.fb_height, 1);
|
||||
|
||||
attr.ta_fgcolor = fg;
|
||||
teken_set_defattr(&gfx_state.tg_teken, &attr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Binary searchable table for CP437 to Unicode conversion.
|
||||
*/
|
||||
struct cp437uni {
|
||||
uint8_t cp437_base;
|
||||
uint16_t unicode_base;
|
||||
uint8_t length;
|
||||
};
|
||||
|
||||
static const struct cp437uni cp437unitable[] = {
|
||||
{ 0, 0x0000, 0 }, { 1, 0x263A, 1 }, { 3, 0x2665, 1 },
|
||||
{ 5, 0x2663, 0 }, { 6, 0x2660, 0 }, { 7, 0x2022, 0 },
|
||||
{ 8, 0x25D8, 0 }, { 9, 0x25CB, 0 }, { 10, 0x25D9, 0 },
|
||||
{ 11, 0x2642, 0 }, { 12, 0x2640, 0 }, { 13, 0x266A, 1 },
|
||||
{ 15, 0x263C, 0 }, { 16, 0x25BA, 0 }, { 17, 0x25C4, 0 },
|
||||
{ 18, 0x2195, 0 }, { 19, 0x203C, 0 }, { 20, 0x00B6, 0 },
|
||||
{ 21, 0x00A7, 0 }, { 22, 0x25AC, 0 }, { 23, 0x21A8, 0 },
|
||||
{ 24, 0x2191, 0 }, { 25, 0x2193, 0 }, { 26, 0x2192, 0 },
|
||||
{ 27, 0x2190, 0 }, { 28, 0x221F, 0 }, { 29, 0x2194, 0 },
|
||||
{ 30, 0x25B2, 0 }, { 31, 0x25BC, 0 }, { 32, 0x0020, 0x5e },
|
||||
{ 127, 0x2302, 0 }, { 128, 0x00C7, 0 }, { 129, 0x00FC, 0 },
|
||||
{ 130, 0x00E9, 0 }, { 131, 0x00E2, 0 }, { 132, 0x00E4, 0 },
|
||||
{ 133, 0x00E0, 0 }, { 134, 0x00E5, 0 }, { 135, 0x00E7, 0 },
|
||||
{ 136, 0x00EA, 1 }, { 138, 0x00E8, 0 }, { 139, 0x00EF, 0 },
|
||||
{ 140, 0x00EE, 0 }, { 141, 0x00EC, 0 }, { 142, 0x00C4, 1 },
|
||||
{ 144, 0x00C9, 0 }, { 145, 0x00E6, 0 }, { 146, 0x00C6, 0 },
|
||||
{ 147, 0x00F4, 0 }, { 148, 0x00F6, 0 }, { 149, 0x00F2, 0 },
|
||||
{ 150, 0x00FB, 0 }, { 151, 0x00F9, 0 }, { 152, 0x00FF, 0 },
|
||||
{ 153, 0x00D6, 0 }, { 154, 0x00DC, 0 }, { 155, 0x00A2, 1 },
|
||||
{ 157, 0x00A5, 0 }, { 158, 0x20A7, 0 }, { 159, 0x0192, 0 },
|
||||
{ 160, 0x00E1, 0 }, { 161, 0x00ED, 0 }, { 162, 0x00F3, 0 },
|
||||
{ 163, 0x00FA, 0 }, { 164, 0x00F1, 0 }, { 165, 0x00D1, 0 },
|
||||
{ 166, 0x00AA, 0 }, { 167, 0x00BA, 0 }, { 168, 0x00BF, 0 },
|
||||
{ 169, 0x2310, 0 }, { 170, 0x00AC, 0 }, { 171, 0x00BD, 0 },
|
||||
{ 172, 0x00BC, 0 }, { 173, 0x00A1, 0 }, { 174, 0x00AB, 0 },
|
||||
{ 175, 0x00BB, 0 }, { 176, 0x2591, 2 }, { 179, 0x2502, 0 },
|
||||
{ 180, 0x2524, 0 }, { 181, 0x2561, 1 }, { 183, 0x2556, 0 },
|
||||
{ 184, 0x2555, 0 }, { 185, 0x2563, 0 }, { 186, 0x2551, 0 },
|
||||
{ 187, 0x2557, 0 }, { 188, 0x255D, 0 }, { 189, 0x255C, 0 },
|
||||
{ 190, 0x255B, 0 }, { 191, 0x2510, 0 }, { 192, 0x2514, 0 },
|
||||
{ 193, 0x2534, 0 }, { 194, 0x252C, 0 }, { 195, 0x251C, 0 },
|
||||
{ 196, 0x2500, 0 }, { 197, 0x253C, 0 }, { 198, 0x255E, 1 },
|
||||
{ 200, 0x255A, 0 }, { 201, 0x2554, 0 }, { 202, 0x2569, 0 },
|
||||
{ 203, 0x2566, 0 }, { 204, 0x2560, 0 }, { 205, 0x2550, 0 },
|
||||
{ 206, 0x256C, 0 }, { 207, 0x2567, 1 }, { 209, 0x2564, 1 },
|
||||
{ 211, 0x2559, 0 }, { 212, 0x2558, 0 }, { 213, 0x2552, 1 },
|
||||
{ 215, 0x256B, 0 }, { 216, 0x256A, 0 }, { 217, 0x2518, 0 },
|
||||
{ 218, 0x250C, 0 }, { 219, 0x2588, 0 }, { 220, 0x2584, 0 },
|
||||
{ 221, 0x258C, 0 }, { 222, 0x2590, 0 }, { 223, 0x2580, 0 },
|
||||
{ 224, 0x03B1, 0 }, { 225, 0x00DF, 0 }, { 226, 0x0393, 0 },
|
||||
{ 227, 0x03C0, 0 }, { 228, 0x03A3, 0 }, { 229, 0x03C3, 0 },
|
||||
{ 230, 0x00B5, 0 }, { 231, 0x03C4, 0 }, { 232, 0x03A6, 0 },
|
||||
{ 233, 0x0398, 0 }, { 234, 0x03A9, 0 }, { 235, 0x03B4, 0 },
|
||||
{ 236, 0x221E, 0 }, { 237, 0x03C6, 0 }, { 238, 0x03B5, 0 },
|
||||
{ 239, 0x2229, 0 }, { 240, 0x2261, 0 }, { 241, 0x00B1, 0 },
|
||||
{ 242, 0x2265, 0 }, { 243, 0x2264, 0 }, { 244, 0x2320, 1 },
|
||||
{ 246, 0x00F7, 0 }, { 247, 0x2248, 0 }, { 248, 0x00B0, 0 },
|
||||
{ 249, 0x2219, 0 }, { 250, 0x00B7, 0 }, { 251, 0x221A, 0 },
|
||||
{ 252, 0x207F, 0 }, { 253, 0x00B2, 0 }, { 254, 0x25A0, 0 },
|
||||
{ 255, 0x00A0, 0 }
|
||||
};
|
||||
|
||||
static uint16_t
|
||||
vga_cp437_to_uni(uint8_t c)
|
||||
{
|
||||
int min, mid, max;
|
||||
|
||||
min = 0;
|
||||
max = (sizeof(cp437unitable) / sizeof(struct cp437uni)) - 1;
|
||||
|
||||
while (max >= min) {
|
||||
mid = (min + max) / 2;
|
||||
if (c < cp437unitable[mid].cp437_base)
|
||||
max = mid - 1;
|
||||
else if (c > cp437unitable[mid].cp437_base +
|
||||
cp437unitable[mid].length)
|
||||
min = mid + 1;
|
||||
else
|
||||
return (c - cp437unitable[mid].cp437_base +
|
||||
cp437unitable[mid].unicode_base);
|
||||
}
|
||||
|
||||
return ('?');
|
||||
}
|
||||
|
||||
/*
|
||||
* install font for text mode
|
||||
*/
|
||||
static void
|
||||
vidc_install_font(void)
|
||||
{
|
||||
static uint8_t fsreg[8] = {0x0, 0x30, 0x5, 0x35, 0xa, 0x3a, 0xf, 0x3f};
|
||||
const uint8_t *from;
|
||||
uint8_t volatile *to;
|
||||
uint16_t c;
|
||||
int i, j, s;
|
||||
int bpc, f_offset;
|
||||
teken_attr_t a = { 0 };
|
||||
|
||||
if (gfx_state.tg_fb_type != FB_TEXT)
|
||||
return;
|
||||
|
||||
/* Sync-reset the sequencer registers */
|
||||
vga_set_seq(VGA_REG_BASE, 0x00, 0x01);
|
||||
/*
|
||||
* enable write to plane2, since fonts
|
||||
* could only be loaded into plane2
|
||||
*/
|
||||
vga_set_seq(VGA_REG_BASE, 0x02, 0x04);
|
||||
/*
|
||||
* sequentially access data in the bit map being
|
||||
* selected by MapMask register (index 0x02)
|
||||
*/
|
||||
vga_set_seq(VGA_REG_BASE, 0x04, 0x07);
|
||||
/* Sync-reset ended, and allow the sequencer to operate */
|
||||
vga_set_seq(VGA_REG_BASE, 0x00, 0x03);
|
||||
|
||||
/*
|
||||
* select plane 2 on Read Mode 0
|
||||
*/
|
||||
vga_set_grc(VGA_REG_BASE, 0x04, 0x02);
|
||||
/*
|
||||
* system addresses sequentially access data, follow
|
||||
* Memory Mode register bit 2 in the sequencer
|
||||
*/
|
||||
vga_set_grc(VGA_REG_BASE, 0x05, 0x00);
|
||||
/*
|
||||
* set range of host memory addresses decoded by VGA
|
||||
* hardware -- A0000h-BFFFFh (128K region)
|
||||
*/
|
||||
vga_set_grc(VGA_REG_BASE, 0x06, 0x00);
|
||||
|
||||
/*
|
||||
* This assumes 8x16 characters, which yield the traditional 80x25
|
||||
* screen.
|
||||
*/
|
||||
bpc = 16;
|
||||
s = 0; /* font slot, maybe should use tunable there. */
|
||||
f_offset = s * 8 * 1024;
|
||||
for (i = 0; i < 256; i++) {
|
||||
c = vga_cp437_to_uni(i);
|
||||
from = font_lookup(&gfx_state.tg_font, c, &a);
|
||||
to = (unsigned char *)ptov(VGA_MEM_BASE) + f_offset +
|
||||
i * 0x20;
|
||||
for (j = 0; j < bpc; j++)
|
||||
*to++ = *from++;
|
||||
}
|
||||
|
||||
/* Sync-reset the sequencer registers */
|
||||
vga_set_seq(VGA_REG_BASE, 0x00, 0x01);
|
||||
/* enable write to plane 0 and 1 */
|
||||
vga_set_seq(VGA_REG_BASE, 0x02, 0x03);
|
||||
/*
|
||||
* enable character map selection
|
||||
* and odd/even addressing
|
||||
*/
|
||||
vga_set_seq(VGA_REG_BASE, 0x04, 0x03);
|
||||
/*
|
||||
* select font map
|
||||
*/
|
||||
vga_set_seq(VGA_REG_BASE, 0x03, fsreg[s]);
|
||||
/* Sync-reset ended, and allow the sequencer to operate */
|
||||
vga_set_seq(VGA_REG_BASE, 0x00, 0x03);
|
||||
|
||||
/* restore graphic registers */
|
||||
|
||||
/* select plane 0 */
|
||||
vga_set_grc(VGA_REG_BASE, 0x04, 0x00);
|
||||
/* enable odd/even addressing mode */
|
||||
vga_set_grc(VGA_REG_BASE, 0x05, 0x10);
|
||||
/*
|
||||
* range of host memory addresses decoded by VGA
|
||||
* hardware -- B8000h-BFFFFh (32K region)
|
||||
*/
|
||||
vga_set_grc(VGA_REG_BASE, 0x06, 0x0e);
|
||||
/* enable all color plane */
|
||||
vga_set_atr(VGA_REG_BASE, 0x12, 0x0f);
|
||||
}
|
||||
|
||||
bool
|
||||
cons_update_mode(bool use_gfx_mode)
|
||||
{
|
||||
const teken_attr_t *a;
|
||||
teken_attr_t attr;
|
||||
char env[10], *ptr;
|
||||
int format, roff, goff, boff;
|
||||
|
||||
gfx_state.tg_tp.tp_row = TEXT_ROWS;
|
||||
gfx_state.tg_tp.tp_col = TEXT_COLS;
|
||||
|
||||
if (use_gfx_mode) {
|
||||
setup_font(&gfx_state, gfx_state.tg_fb.fb_height,
|
||||
gfx_state.tg_fb.fb_width);
|
||||
/* Point of origin in pixels. */
|
||||
gfx_state.tg_origin.tp_row = (gfx_state.tg_fb.fb_height -
|
||||
(gfx_state.tg_tp.tp_row * gfx_state.tg_font.vf_height)) / 2;
|
||||
gfx_state.tg_origin.tp_col = (gfx_state.tg_fb.fb_width -
|
||||
(gfx_state.tg_tp.tp_col * gfx_state.tg_font.vf_width)) / 2;
|
||||
|
||||
gfx_state.tg_glyph_size = gfx_state.tg_font.vf_height *
|
||||
gfx_state.tg_font.vf_width * 4;
|
||||
free(gfx_state.tg_glyph);
|
||||
gfx_state.tg_glyph = malloc(gfx_state.tg_glyph_size);
|
||||
if (gfx_state.tg_glyph == NULL)
|
||||
return (false);
|
||||
gfx_state.tg_functions = &tfx;
|
||||
snprintf(env, sizeof (env), "%d", gfx_state.tg_fb.fb_height);
|
||||
env_setenv("screen.height", EV_VOLATILE | EV_NOHOOK, env,
|
||||
env_noset, env_screen_nounset);
|
||||
snprintf(env, sizeof (env), "%d", gfx_state.tg_fb.fb_width);
|
||||
env_setenv("screen.width", EV_VOLATILE | EV_NOHOOK, env,
|
||||
env_noset, env_screen_nounset);
|
||||
snprintf(env, sizeof (env), "%d", gfx_state.tg_fb.fb_bpp);
|
||||
env_setenv("screen.depth", EV_VOLATILE | EV_NOHOOK, env,
|
||||
env_noset, env_screen_nounset);
|
||||
} else {
|
||||
/* Trigger loading of 8x16 font. */
|
||||
setup_font(&gfx_state,
|
||||
16 * gfx_state.tg_fb.fb_height + BORDER_PIXELS,
|
||||
8 * gfx_state.tg_fb.fb_width + BORDER_PIXELS);
|
||||
gfx_state.tg_functions = &tf;
|
||||
/* ensure the following are not set for text mode */
|
||||
unsetenv("screen.height");
|
||||
unsetenv("screen.width");
|
||||
unsetenv("screen.depth");
|
||||
unsetenv("kern.vt.fb.default_mode");
|
||||
vidc_install_font();
|
||||
}
|
||||
|
||||
free(screen_buffer);
|
||||
screen_buffer = malloc(gfx_state.tg_tp.tp_row * gfx_state.tg_tp.tp_col *
|
||||
sizeof(*screen_buffer));
|
||||
if (screen_buffer == NULL)
|
||||
return (false);
|
||||
|
||||
teken_init(&gfx_state.tg_teken, gfx_state.tg_functions, &gfx_state);
|
||||
|
||||
if (gfx_state.tg_ctype == CT_INDEXED)
|
||||
format = COLOR_FORMAT_VGA;
|
||||
else
|
||||
format = COLOR_FORMAT_RGB;
|
||||
|
||||
roff = ffs(gfx_state.tg_fb.fb_mask_red) - 1;
|
||||
goff = ffs(gfx_state.tg_fb.fb_mask_green) - 1;
|
||||
boff = ffs(gfx_state.tg_fb.fb_mask_blue) - 1;
|
||||
(void) generate_cons_palette(cmap, format,
|
||||
gfx_state.tg_fb.fb_mask_red >> roff, roff,
|
||||
gfx_state.tg_fb.fb_mask_green >> goff, goff,
|
||||
gfx_state.tg_fb.fb_mask_blue >> boff, boff);
|
||||
|
||||
if (gfx_state.tg_ctype == CT_INDEXED)
|
||||
vidc_load_palette(cmap);
|
||||
|
||||
teken_set_winsize(&gfx_state.tg_teken, &gfx_state.tg_tp);
|
||||
a = teken_get_defattr(&gfx_state.tg_teken);
|
||||
attr = *a;
|
||||
|
||||
/*
|
||||
* On first run, we set up the vidc_set_colors()
|
||||
* callback. If the env is already set, we
|
||||
* pick up fg and bg color values from the environment.
|
||||
*/
|
||||
ptr = getenv("teken.fg_color");
|
||||
if (ptr != NULL) {
|
||||
attr.ta_fgcolor = strtol(ptr, NULL, 10);
|
||||
ptr = getenv("teken.bg_color");
|
||||
attr.ta_bgcolor = strtol(ptr, NULL, 10);
|
||||
|
||||
teken_set_defattr(&gfx_state.tg_teken, &attr);
|
||||
} else {
|
||||
snprintf(env, sizeof(env), "%d", attr.ta_fgcolor);
|
||||
env_setenv("teken.fg_color", EV_VOLATILE, env,
|
||||
vidc_set_colors, env_nounset);
|
||||
snprintf(env, sizeof(env), "%d", attr.ta_bgcolor);
|
||||
env_setenv("teken.bg_color", EV_VOLATILE, env,
|
||||
vidc_set_colors, env_nounset);
|
||||
}
|
||||
|
||||
/* Improve visibility */
|
||||
if (attr.ta_bgcolor == TC_WHITE)
|
||||
attr.ta_bgcolor |= TC_LIGHT;
|
||||
teken_set_defattr(&gfx_state.tg_teken, &attr);
|
||||
|
||||
snprintf(env, sizeof (env), "%u", (unsigned)gfx_state.tg_tp.tp_row);
|
||||
setenv("LINES", env, 1);
|
||||
snprintf(env, sizeof (env), "%u", (unsigned)gfx_state.tg_tp.tp_col);
|
||||
setenv("COLUMNS", env, 1);
|
||||
|
||||
/* Draw frame around terminal area. */
|
||||
cons_draw_frame(&attr);
|
||||
/* Erase display, this will also fill our screen buffer. */
|
||||
teken_input(&gfx_state.tg_teken, "\e[2J", 4);
|
||||
gfx_state.tg_functions->tf_param(&gfx_state, TP_SHOWCURSOR, 1);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static int
|
||||
vidc_init(int arg)
|
||||
{
|
||||
@ -670,6 +989,7 @@ vidc_init(int arg)
|
||||
return (0);
|
||||
|
||||
vidc_started = 1;
|
||||
vbe_init();
|
||||
|
||||
/*
|
||||
* Check Miscellaneous Output Register (Read at 3CCh, Write at 3C2h)
|
||||
@ -687,31 +1007,20 @@ vidc_init(int arg)
|
||||
val &= ~VGA_AC_MC_ELG;
|
||||
vga_set_atr(VGA_REG_BASE, VGA_AC_MODE_CONTROL, val);
|
||||
|
||||
tp.tp_row = TEXT_ROWS;
|
||||
tp.tp_col = TEXT_COLS;
|
||||
buffer = malloc(tp.tp_row * tp.tp_col * sizeof(*buffer));
|
||||
if (buffer == NULL)
|
||||
#if defined(FRAMEBUFFER_MODE)
|
||||
val = vbe_default_mode();
|
||||
/* if val is not legal VBE mode, use text mode */
|
||||
if (VBE_VALID_MODE(val)) {
|
||||
if (vbe_set_mode(val) != 0)
|
||||
bios_set_text_mode(VGA_TEXT_MODE);
|
||||
}
|
||||
#endif
|
||||
|
||||
gfx_framework_init();
|
||||
|
||||
if (!cons_update_mode(VBE_VALID_MODE(vbe_get_mode())))
|
||||
return (1);
|
||||
|
||||
snprintf(env, sizeof (env), "%u", tp.tp_row);
|
||||
setenv("LINES", env, 1);
|
||||
snprintf(env, sizeof (env), "%u", tp.tp_col);
|
||||
setenv("COLUMNS", env, 1);
|
||||
|
||||
teken_init(&teken, &tf, NULL);
|
||||
teken_set_winsize(&teken, &tp);
|
||||
a = teken_get_defattr(&teken);
|
||||
|
||||
snprintf(env, sizeof(env), "%d", a->ta_fgcolor);
|
||||
env_setenv("teken.fg_color", EV_VOLATILE, env, vidc_set_colors,
|
||||
env_nounset);
|
||||
snprintf(env, sizeof(env), "%d", a->ta_bgcolor);
|
||||
env_setenv("teken.bg_color", EV_VOLATILE, env, vidc_set_colors,
|
||||
env_nounset);
|
||||
|
||||
/* Erase display, this will also fill our screen buffer. */
|
||||
teken_input(&teken, "\e[J", 3);
|
||||
|
||||
for (int i = 0; i < 10 && vidc_ischar(); i++)
|
||||
(void) vidc_getchar();
|
||||
|
||||
@ -734,8 +1043,8 @@ vidc_putchar(int c)
|
||||
{
|
||||
unsigned char ch = c;
|
||||
|
||||
if (buffer != NULL)
|
||||
teken_input(&teken, &ch, sizeof (ch));
|
||||
if (screen_buffer != NULL)
|
||||
teken_input(&gfx_state.tg_teken, &ch, sizeof (ch));
|
||||
else
|
||||
vidc_biosputchar(c);
|
||||
}
|
||||
|
@ -23,7 +23,13 @@ VERSION_FILE= ${.CURDIR}/../loader/version
|
||||
.PATH: ${BOOTSRC}/i386/loader
|
||||
|
||||
# architecture-specific loader code
|
||||
SRCS= main.c conf.c vers.c chain.c
|
||||
SRCS= main.c conf.c vers.c chain.c gfx_fb.c 8x16.c
|
||||
|
||||
CFLAGS.gfx_fb.c += -I${.CURDIR}/../libi386
|
||||
CFLAGS.gfx_fb.c += -I$(SRCTOP)/sys/teken
|
||||
CFLAGS.gfx_fb.c += -I${SRCTOP}/sys/cddl/contrib/opensolaris/common/lz4
|
||||
CFLAGS.gfx_fb.c += -I${SRCTOP}/contrib/pnglite
|
||||
CFLAGS.gfx_fb.c += -DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib
|
||||
|
||||
# Include bcache code.
|
||||
HAVE_BCACHE= yes
|
||||
@ -49,7 +55,7 @@ HELP_FILES= ${.CURDIR}/help.i386
|
||||
# Always add MI sources
|
||||
.include "${BOOTSRC}/loader.mk"
|
||||
|
||||
CLEANFILES+= ${LOADER} ${LOADER}.bin
|
||||
CLEANFILES+= ${LOADER} ${LOADER}.bin 8x16.c
|
||||
|
||||
ORG= 0x0
|
||||
|
||||
@ -64,6 +70,9 @@ CFLAGS+= -I${BOOTSRC}/i386
|
||||
#CFLAGS+= -g
|
||||
#LDFLAGS+= -g
|
||||
|
||||
8x16.c: ${SRCTOP}/contrib/terminus/ter-u16v.bdf
|
||||
vtfontcvt -f compressed-source -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
${LOADER}: ${LOADER}.bin ${BTXLDR} ${BTXKERN}
|
||||
btxld -v -f aout -e ${LOADER_ADDRESS} -o ${.TARGET} -l ${BTXLDR} \
|
||||
-b ${BTXKERN} ${LOADER}.bin
|
||||
|
@ -130,6 +130,12 @@ main(void)
|
||||
}
|
||||
setheap(heap_bottom, heap_top);
|
||||
|
||||
/*
|
||||
* detect ACPI for future reference. This may set console to comconsole
|
||||
* if we do have ACPI SPCR table.
|
||||
*/
|
||||
biosacpi_detect();
|
||||
|
||||
/*
|
||||
* XXX Chicken-and-egg problem; we want to have console output early,
|
||||
* but some console attributes may depend on reading from eg. the boot
|
||||
@ -242,9 +248,6 @@ main(void)
|
||||
initial_bootinfo->bi_extmem = bios_extmem / 1024;
|
||||
}
|
||||
|
||||
/* detect ACPI for future reference */
|
||||
biosacpi_detect();
|
||||
|
||||
/* detect SMBIOS for future reference */
|
||||
smbios_detect(NULL);
|
||||
|
||||
@ -254,6 +257,7 @@ main(void)
|
||||
printf("\n%s", bootprog_info);
|
||||
|
||||
extract_currdev(); /* set $currdev and $loaddev */
|
||||
autoload_font(true);
|
||||
|
||||
bios_getsmap();
|
||||
|
||||
|
9
stand/images/Makefile
Normal file
9
stand/images/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <bsd.init.mk>
|
||||
|
||||
FILES+= freebsd-brand-rev.png freebsd-brand.png freebsd-logo-rev.png
|
||||
|
||||
FILESDIR= /boot/images
|
||||
|
||||
.include <bsd.prog.mk>
|
BIN
stand/images/freebsd-brand-rev.png
Normal file
BIN
stand/images/freebsd-brand-rev.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.5 KiB |
BIN
stand/images/freebsd-brand.png
Normal file
BIN
stand/images/freebsd-brand.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
stand/images/freebsd-logo-rev.png
Normal file
BIN
stand/images/freebsd-logo-rev.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
@ -35,6 +35,8 @@ CFLAGS+= -ffreestanding -nostdlib -DLUA_USE_POSIX
|
||||
CFLAGS+= -fno-stack-protector -D__BSD_VISIBLE
|
||||
CFLAGS+= -I${BOOTSRC}/include -I${LIBLUASRC} -I${LUASRC} -I${LDRSRC}
|
||||
|
||||
CFLAGS.lutils.c+= -I${SRCTOP}/sys/teken -I${SRCTOP}/contrib/pnglite
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "amd64" && ${DO32:U0} == 0
|
||||
CFLAGS+= -fPIC
|
||||
.endif
|
||||
|
@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include "lstd.h"
|
||||
#include "lutils.h"
|
||||
#include "bootstrap.h"
|
||||
#include <gfx_fb.h>
|
||||
#include <pnglite.h>
|
||||
|
||||
/*
|
||||
* Like loader.perform, except args are passed already parsed
|
||||
@ -346,6 +348,189 @@ lua_writefile(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* put image using terminal coordinates.
|
||||
*/
|
||||
static int
|
||||
lua_term_putimage(lua_State *L)
|
||||
{
|
||||
const char *name;
|
||||
png_t png;
|
||||
uint32_t x1, y1, x2, y2, f;
|
||||
int nargs, ret = 0, error;
|
||||
|
||||
nargs = lua_gettop(L);
|
||||
if (nargs != 6) {
|
||||
lua_pushboolean(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
name = luaL_checkstring(L, 1);
|
||||
x1 = luaL_checknumber(L, 2);
|
||||
y1 = luaL_checknumber(L, 3);
|
||||
x2 = luaL_checknumber(L, 4);
|
||||
y2 = luaL_checknumber(L, 5);
|
||||
f = luaL_checknumber(L, 6);
|
||||
|
||||
x1 = gfx_state.tg_origin.tp_col + x1 * gfx_state.tg_font.vf_width;
|
||||
y1 = gfx_state.tg_origin.tp_row + y1 * gfx_state.tg_font.vf_height;
|
||||
if (x2 != 0) {
|
||||
x2 = gfx_state.tg_origin.tp_col +
|
||||
x2 * gfx_state.tg_font.vf_width;
|
||||
}
|
||||
if (y2 != 0) {
|
||||
y2 = gfx_state.tg_origin.tp_row +
|
||||
y2 * gfx_state.tg_font.vf_height;
|
||||
}
|
||||
|
||||
if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
|
||||
if (f & FL_PUTIMAGE_DEBUG)
|
||||
printf("%s\n", png_error_string(error));
|
||||
} else {
|
||||
if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
|
||||
ret = 1;
|
||||
(void) png_close(&png);
|
||||
}
|
||||
lua_pushboolean(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lua_fb_putimage(lua_State *L)
|
||||
{
|
||||
const char *name;
|
||||
png_t png;
|
||||
uint32_t x1, y1, x2, y2, f;
|
||||
int nargs, ret = 0, error;
|
||||
|
||||
nargs = lua_gettop(L);
|
||||
if (nargs != 6) {
|
||||
lua_pushboolean(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
name = luaL_checkstring(L, 1);
|
||||
x1 = luaL_checknumber(L, 2);
|
||||
y1 = luaL_checknumber(L, 3);
|
||||
x2 = luaL_checknumber(L, 4);
|
||||
y2 = luaL_checknumber(L, 5);
|
||||
f = luaL_checknumber(L, 6);
|
||||
|
||||
if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
|
||||
if (f & FL_PUTIMAGE_DEBUG)
|
||||
printf("%s\n", png_error_string(error));
|
||||
} else {
|
||||
if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
|
||||
ret = 1;
|
||||
(void) png_close(&png);
|
||||
}
|
||||
lua_pushboolean(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lua_fb_setpixel(lua_State *L)
|
||||
{
|
||||
uint32_t x, y;
|
||||
int nargs;
|
||||
|
||||
nargs = lua_gettop(L);
|
||||
if (nargs != 2) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
x = luaL_checknumber(L, 1);
|
||||
y = luaL_checknumber(L, 2);
|
||||
gfx_fb_setpixel(x, y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lua_fb_line(lua_State *L)
|
||||
{
|
||||
uint32_t x0, y0, x1, y1, wd;
|
||||
int nargs;
|
||||
|
||||
nargs = lua_gettop(L);
|
||||
if (nargs != 5) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
x0 = luaL_checknumber(L, 1);
|
||||
y0 = luaL_checknumber(L, 2);
|
||||
x1 = luaL_checknumber(L, 3);
|
||||
y1 = luaL_checknumber(L, 4);
|
||||
wd = luaL_checknumber(L, 5);
|
||||
gfx_fb_line(x0, y0, x1, y1, wd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lua_fb_bezier(lua_State *L)
|
||||
{
|
||||
uint32_t x0, y0, x1, y1, x2, y2, width;
|
||||
int nargs;
|
||||
|
||||
nargs = lua_gettop(L);
|
||||
if (nargs != 7) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
x0 = luaL_checknumber(L, 1);
|
||||
y0 = luaL_checknumber(L, 2);
|
||||
x1 = luaL_checknumber(L, 3);
|
||||
y1 = luaL_checknumber(L, 4);
|
||||
x2 = luaL_checknumber(L, 5);
|
||||
y2 = luaL_checknumber(L, 6);
|
||||
width = luaL_checknumber(L, 7);
|
||||
gfx_fb_bezier(x0, y0, x1, y1, x2, y2, width);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lua_fb_drawrect(lua_State *L)
|
||||
{
|
||||
uint32_t x0, y0, x1, y1, fill;
|
||||
int nargs;
|
||||
|
||||
nargs = lua_gettop(L);
|
||||
if (nargs != 5) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
x0 = luaL_checknumber(L, 1);
|
||||
y0 = luaL_checknumber(L, 2);
|
||||
x1 = luaL_checknumber(L, 3);
|
||||
y1 = luaL_checknumber(L, 4);
|
||||
fill = luaL_checknumber(L, 5);
|
||||
gfx_fb_drawrect(x0, y0, x1, y1, fill);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lua_term_drawrect(lua_State *L)
|
||||
{
|
||||
uint32_t x0, y0, x1, y1;
|
||||
int nargs;
|
||||
|
||||
nargs = lua_gettop(L);
|
||||
if (nargs != 4) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
x0 = luaL_checknumber(L, 1);
|
||||
y0 = luaL_checknumber(L, 2);
|
||||
x1 = luaL_checknumber(L, 3);
|
||||
y1 = luaL_checknumber(L, 4);
|
||||
gfx_term_drawrect(x0, y0, x1, y1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define REG_SIMPLE(n) { #n, lua_ ## n }
|
||||
static const struct luaL_Reg loaderlib[] = {
|
||||
REG_SIMPLE(delay),
|
||||
@ -360,6 +545,13 @@ static const struct luaL_Reg loaderlib[] = {
|
||||
REG_SIMPLE(setenv),
|
||||
REG_SIMPLE(time),
|
||||
REG_SIMPLE(unsetenv),
|
||||
REG_SIMPLE(fb_bezier),
|
||||
REG_SIMPLE(fb_drawrect),
|
||||
REG_SIMPLE(fb_line),
|
||||
REG_SIMPLE(fb_putimage),
|
||||
REG_SIMPLE(fb_setpixel),
|
||||
REG_SIMPLE(term_drawrect),
|
||||
REG_SIMPLE(term_putimage),
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
|
@ -8,9 +8,15 @@ SRCS+= boot.c commands.c console.c devopen.c interp.c
|
||||
SRCS+= interp_backslash.c interp_parse.c ls.c misc.c
|
||||
SRCS+= module.c nvstore.c
|
||||
|
||||
CFLAGS.module.c += -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite
|
||||
|
||||
.if ${MACHINE} == "i386" || ${MACHINE_CPUARCH} == "amd64"
|
||||
SRCS+= load_elf32.c load_elf32_obj.c reloc_elf32.c
|
||||
SRCS+= load_elf64.c load_elf64_obj.c reloc_elf64.c
|
||||
SRCS+= pnglite.c
|
||||
.PATH: ${SRCTOP}/contrib/pnglite
|
||||
CFLAGS.pnglite.c+= -I${SRCTOP}/contrib/pnglite
|
||||
CFLAGS.pnglite.c+= -DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib
|
||||
.elif ${MACHINE_CPUARCH} == "aarch64"
|
||||
SRCS+= load_elf64.c reloc_elf64.c
|
||||
.elif ${MACHINE_CPUARCH} == "arm"
|
||||
|
@ -56,7 +56,7 @@ function color.isEnabled()
|
||||
if c ~= nil then
|
||||
return c:lower() ~= "no" and c ~= "0"
|
||||
end
|
||||
return not core.isSerialBoot()
|
||||
return true
|
||||
end
|
||||
|
||||
function color.escapefg(color_value)
|
||||
|
@ -383,6 +383,19 @@ function core.isZFSBoot()
|
||||
return false
|
||||
end
|
||||
|
||||
function core.isFramebufferConsole()
|
||||
local c = loader.getenv("console")
|
||||
if c ~= nil then
|
||||
if c:find("efi") == nil and c:find("vidconsole") == nil then
|
||||
return false
|
||||
end
|
||||
if loader.getenv("screen.depth") ~= nil then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function core.isSerialConsole()
|
||||
local c = loader.getenv("console")
|
||||
if c ~= nil then
|
||||
|
@ -202,7 +202,7 @@ local function defaultframe()
|
||||
return "double"
|
||||
end
|
||||
|
||||
local function drawbox()
|
||||
local function drawframe()
|
||||
local x = menu_position.x - 3
|
||||
local y = menu_position.y - 1
|
||||
local w = frame_size.w
|
||||
@ -213,7 +213,7 @@ local function drawbox()
|
||||
-- If we don't have a framespec for the current frame style, just don't
|
||||
-- draw a box.
|
||||
if framespec == nil then
|
||||
return
|
||||
return false
|
||||
end
|
||||
|
||||
local hl = framespec.horizontal
|
||||
@ -227,6 +227,11 @@ local function drawbox()
|
||||
x = x + shift.x
|
||||
y = y + shift.y
|
||||
|
||||
if core.isFramebufferConsole() and loader.term_drawrect ~= nil then
|
||||
loader.term_drawrect(x, y, x + w, y + h)
|
||||
return true
|
||||
end
|
||||
|
||||
screen.setcursor(x, y); printc(tl)
|
||||
screen.setcursor(x, y + h); printc(bl)
|
||||
screen.setcursor(x + w, y); printc(tr)
|
||||
@ -248,12 +253,25 @@ local function drawbox()
|
||||
screen.setcursor(x + w, y + i)
|
||||
printc(vl)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function drawbox()
|
||||
local x = menu_position.x - 3
|
||||
local y = menu_position.y - 1
|
||||
local w = frame_size.w
|
||||
local menu_header = loader.getenv("loader_menu_title") or
|
||||
"Welcome to FreeBSD"
|
||||
local menu_header_align = loader.getenv("loader_menu_title_align")
|
||||
local menu_header_x
|
||||
|
||||
x = x + shift.x
|
||||
y = y + shift.y
|
||||
|
||||
if drawframe(x, y, w) == false then
|
||||
return
|
||||
end
|
||||
|
||||
if menu_header_align ~= nil then
|
||||
menu_header_align = menu_header_align:lower()
|
||||
if menu_header_align == "left" then
|
||||
@ -287,6 +305,14 @@ local function drawbrand()
|
||||
|
||||
x = x + shift.x
|
||||
y = y + shift.y
|
||||
if core.isFramebufferConsole() and
|
||||
loader.term_putimage ~= nil and
|
||||
branddef.image ~= nil then
|
||||
if loader.term_putimage(branddef.image, 0, 0, 0, 7, 0)
|
||||
then
|
||||
return true
|
||||
end
|
||||
end
|
||||
draw(x, y, graphic)
|
||||
end
|
||||
|
||||
@ -330,9 +356,33 @@ local function drawlogo()
|
||||
y = y + logodef.shift.y
|
||||
end
|
||||
|
||||
if core.isFramebufferConsole() and
|
||||
loader.term_putimage ~= nil and
|
||||
logodef.image ~= nil then
|
||||
local y1 = 15
|
||||
|
||||
if logodef.image_rl ~= nil then
|
||||
y1 = logodef.image_rl
|
||||
end
|
||||
if loader.term_putimage(logodef.image, x, y, 0, y + y1, 0)
|
||||
then
|
||||
return true
|
||||
end
|
||||
end
|
||||
draw(x, y, logodef.graphic)
|
||||
end
|
||||
|
||||
local function drawitem(func)
|
||||
local console = loader.getenv("console")
|
||||
local c
|
||||
|
||||
for c in string.gmatch(console, "%w+") do
|
||||
loader.setenv("console", c)
|
||||
func()
|
||||
end
|
||||
loader.setenv("console", console)
|
||||
end
|
||||
|
||||
fbsd_brand = {
|
||||
" ______ ____ _____ _____ ",
|
||||
" | ____| | _ \\ / ____| __ \\ ",
|
||||
@ -378,6 +428,7 @@ branddefs = {
|
||||
-- keys are: graphic (table depicting graphic)
|
||||
["fbsd"] = {
|
||||
graphic = fbsd_brand,
|
||||
image = "/boot/images/freebsd-brand-rev.png",
|
||||
},
|
||||
["none"] = {
|
||||
graphic = none,
|
||||
@ -458,9 +509,9 @@ drawer.frame_styles = {
|
||||
function drawer.drawscreen(menudef)
|
||||
-- drawlogo() must go first.
|
||||
-- it determines the positions of other elements
|
||||
drawlogo()
|
||||
drawbrand()
|
||||
drawbox()
|
||||
drawitem(drawlogo)
|
||||
drawitem(drawbrand)
|
||||
drawitem(drawbox)
|
||||
return drawmenu(menudef)
|
||||
end
|
||||
|
||||
|
@ -47,6 +47,8 @@ return {
|
||||
" .---.....----.\027[m",
|
||||
},
|
||||
requires_color = true,
|
||||
shift = {x = 2, y = 4},
|
||||
shift = {x = 2, y = 3},
|
||||
image = "/boot/images/freebsd-logo-rev.png",
|
||||
image_rl = 15
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ CFLAGS+= -I${BOOTSRC}/userboot
|
||||
CFLAGS.main.c+= -I${BOOTSRC}/libsa/zfs
|
||||
CFLAGS.main.c+= -I${SYSDIR}/contrib/openzfs/include
|
||||
CFLAGS.main.c+= -I${SYSDIR}/contrib/openzfs/include/os/freebsd/zfs
|
||||
CFLAGS.userboot_cons.c+= -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite
|
||||
CWARNFLAGS.main.c += -Wno-implicit-function-declaration
|
||||
|
||||
LDFLAGS+= -nostdlib -Wl,-Bsymbolic
|
||||
|
@ -28,9 +28,14 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stand.h>
|
||||
#include <sys/font.h>
|
||||
#include "gfx_fb.h"
|
||||
#include "bootstrap.h"
|
||||
#include "libuserboot.h"
|
||||
|
||||
font_list_t fonts = STAILQ_HEAD_INITIALIZER(fonts);
|
||||
teken_gfx_t gfx_state = { 0 };
|
||||
|
||||
int console;
|
||||
|
||||
static struct console *userboot_comconsp;
|
||||
|
@ -93,9 +93,10 @@ typedef struct vt_font_bitmap_data {
|
||||
} vt_font_bitmap_data_t;
|
||||
|
||||
typedef enum {
|
||||
FONT_AUTO,
|
||||
FONT_MANUAL,
|
||||
FONT_BOOT
|
||||
FONT_AUTO, /* This font is loaded by software */
|
||||
FONT_MANUAL, /* This font is loaded manually by user */
|
||||
FONT_BUILTIN, /* This font was built in at compile time */
|
||||
FONT_RELOAD /* This font is marked to be re-read from file */
|
||||
} FONT_FLAGS;
|
||||
|
||||
struct fontlist {
|
||||
|
@ -48,6 +48,7 @@ typedef unsigned char teken_format_t;
|
||||
#define TF_BLINK 0x04 /* Blinking character. */
|
||||
#define TF_REVERSE 0x08 /* Reverse rendered character. */
|
||||
#define TF_CJK_RIGHT 0x10 /* Right-hand side of CJK character. */
|
||||
#define TF_IMAGE 0x20 /* This character space has image. */
|
||||
typedef unsigned char teken_color_t;
|
||||
#define TC_BLACK 0
|
||||
#define TC_RED 1
|
||||
|
Loading…
Reference in New Issue
Block a user