Print this page
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    9259 libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>


  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright 2017 Toomas Soome <tsoome@me.com>
  29  */
  30 
  31 /*
  32  * Generic font related data and functions shared by early boot console
  33  * in dboot, kernel startup and full kernel.
  34  */
  35 #include <sys/types.h>
  36 #include <sys/systm.h>

  37 #include <sys/font.h>
  38 #include <sys/sysmacros.h>
  39 
  40 /*


































  41  * Fonts are statically linked with this module. At some point an
  42  * RFE might be desireable to allow dynamic font loading.  The
  43  * original intention to facilitate dynamic fonts can be seen
  44  * by examining the data structures and set_font().  As much of
  45  * the original code is retained but modified to be suited for
  46  * traversing a list of static fonts.
  47  */
  48 
  49 /*
  50  * Must be sorted by font size in descending order
  51  */
  52 struct fontlist fonts[] = {
  53         {  &font_data_12x22,        NULL  },
  54         {  &font_data_8x16, NULL  },
  55         {  &font_data_7x14, NULL  },
  56         {  &font_data_6x10, NULL  },
  57         {  NULL, NULL  }
  58 };
  59 
  60 void
  61 set_font(struct font *f, short *rows, short *cols, short height, short width)
  62 {
  63         bitmap_data_t   *font_selected = NULL;
  64         struct fontlist *fl;
  65         int i;
  66 
  67         /*























  68          * Find best font for these dimensions, or use default
  69          *
  70          * A 1 pixel border is the absolute minimum we could have
  71          * as a border around the text window (BORDER_PIXELS = 2),
  72          * however a slightly larger border not only looks better
  73          * but for the fonts currently statically built into the
  74          * emulator causes much better font selection for the
  75          * normal range of screen resolutions.
  76          */
  77         for (fl = fonts; fl->data; fl++) {
  78                 if ((((*rows * fl->data->height) + BORDER_PIXELS) <= height) &&
  79                     (((*cols * fl->data->width) + BORDER_PIXELS) <= width)) {
  80                         font_selected = fl->data;










  81                         break;
  82                 }

  83         }


  84         /*
  85          * The minus 2 is to make sure we have at least a 1 pixel
  86          * border around the entire screen.
  87          */
  88         if (font_selected == NULL) {
  89                 if (((*rows * DEFAULT_FONT_DATA.height) > height) ||
  90                     ((*cols * DEFAULT_FONT_DATA.width) > width)) {
  91                         *rows = (height - 2) / DEFAULT_FONT_DATA.height;
  92                         *cols = (width - 2) / DEFAULT_FONT_DATA.width;
  93                 }
  94                 font_selected = &DEFAULT_FONT_DATA;




  95         }
  96 
  97         f->width = font_selected->width;
  98         f->height = font_selected->height;
  99 
 100         for (i = 0; i < ENCODED_CHARS; i++)
 101                 f->char_ptr[i] = font_selected->encoding[i];



 102 
 103         f->image_data = font_selected->image;

 104 

























 105 }
 106 
 107 /*




























 108  * bit_to_pix4 is for 4-bit frame buffers.  It will write one output byte
 109  * for each 2 bits of input bitmap.  It inverts the input bits before
 110  * doing the output translation, for reverse video.
 111  *
 112  * Assuming foreground is 0001 and background is 0000...
 113  * An input data byte of 0x53 will output the bit pattern
 114  * 00000001 00000001 00000000 00010001.
 115  */
 116 
 117 void
 118 font_bit_to_pix4(
 119     struct font *f,
 120     uint8_t *dest,
 121     uint8_t c,
 122     uint8_t fg_color,
 123     uint8_t bg_color)
 124 {
 125         int     row;
 126         int     byte;
 127         int     i;
 128         uint8_t *cp;
 129         uint8_t data;
 130         uint8_t nibblett;
 131         int     bytes_wide;
 132 
 133         cp = f->char_ptr[c];
 134         bytes_wide = (f->width + 7) / 8;
 135 
 136         for (row = 0; row < f->height; row++) {
 137                 for (byte = 0; byte < bytes_wide; byte++) {
 138                         data = *cp++;
 139                         for (i = 0; i < 4; i++) {
 140                                 nibblett = (data >> ((3-i) * 2)) & 0x3;
 141                                 switch (nibblett) {
 142                                 case 0x0:
 143                                         *dest++ = bg_color << 4 | bg_color;
 144                                         break;
 145                                 case 0x1:
 146                                         *dest++ = bg_color << 4 | fg_color;
 147                                         break;
 148                                 case 0x2:
 149                                         *dest++ = fg_color << 4 | bg_color;
 150                                         break;
 151                                 case 0x3:
 152                                         *dest++ = fg_color << 4 | fg_color;
 153                                         break;
 154                                 }
 155                         }
 156                 }
 157         }
 158 }
 159 
 160 /*
 161  * bit_to_pix8 is for 8-bit frame buffers.  It will write one output byte
 162  * for each bit of input bitmap.  It inverts the input bits before
 163  * doing the output translation, for reverse video.
 164  *
 165  * Assuming foreground is 00000001 and background is 00000000...
 166  * An input data byte of 0x53 will output the bit pattern
 167  * 0000000 000000001 00000000 00000001 00000000 00000000 00000001 00000001.
 168  */
 169 
 170 void
 171 font_bit_to_pix8(
 172     struct font *f,
 173     uint8_t *dest,
 174     uint8_t c,
 175     uint8_t fg_color,
 176     uint8_t bg_color)
 177 {
 178         int     row;
 179         int     byte;
 180         int     i;
 181         uint8_t *cp;
 182         uint8_t data;
 183         int     bytes_wide;
 184         uint8_t mask;
 185         int     bitsleft, nbits;
 186 
 187         cp = f->char_ptr[c];
 188         bytes_wide = (f->width + 7) / 8;
 189 
 190         for (row = 0; row < f->height; row++) {
 191                 bitsleft = f->width;
 192                 for (byte = 0; byte < bytes_wide; byte++) {
 193                         data = *cp++;
 194                         mask = 0x80;
 195                         nbits = MIN(8, bitsleft);
 196                         bitsleft -= nbits;
 197                         for (i = 0; i < nbits; i++) {
 198                                 *dest++ = (data & mask ? fg_color: bg_color);
 199                                 mask = mask >> 1;
 200                         }
 201                 }
 202         }
 203 }
 204 
 205 /*
 206  * bit_to_pix24 is for 24-bit frame buffers.  It will write four output bytes
 207  * for each bit of input bitmap.  It inverts the input bits before














































































































 208  * doing the output translation, for reverse video.  Note that each
 209  * 24-bit RGB value is finally stored in a 32-bit unsigned int, with the
 210  * high-order byte set to zero.
 211  *
 212  * Assuming foreground is 00000000 11111111 11111111 11111111
 213  * and background is 00000000 00000000 00000000 00000000
 214  * An input data byte of 0x53 will output the bit pattern
 215  *
 216  * 00000000 00000000 00000000 00000000
 217  * 00000000 11111111 11111111 11111111
 218  * 00000000 00000000 00000000 00000000
 219  * 00000000 11111111 11111111 11111111
 220  * 00000000 00000000 00000000 00000000
 221  * 00000000 00000000 00000000 00000000
 222  * 00000000 11111111 11111111 11111111
 223  * 00000000 11111111 11111111 11111111
 224  *
 225  */
 226 
 227 void
 228 font_bit_to_pix24(
 229     struct font *f,
 230     uint32_t *dest,
 231     uint8_t c,
 232     uint32_t fg_color32,
 233     uint32_t bg_color32)
 234 {
 235         int     row;
 236         int     byte;
 237         int     i;
 238         uint8_t *cp;
 239         uint32_t data;
 240         int     bytes_wide;
 241         int     bitsleft, nbits;
 242 
 243         cp = f->char_ptr[c];
 244         bytes_wide = (f->width + 7) / 8;


 245 
 246         for (row = 0; row < f->height; row++) {
 247                 bitsleft = f->width;



 248                 for (byte = 0; byte < bytes_wide; byte++) {

 249                         data = *cp++;


 250                         nbits = MIN(8, bitsleft);
 251                         bitsleft -= nbits;
 252                         for (i = 0; i < nbits; i++) {
 253                                 *dest++ = ((data << i) & 0x80 ?
 254                                     fg_color32 : bg_color32);
 255                         }
 256                 }
 257         }
 258 }


  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright 2017 Toomas Soome <tsoome@me.com>
  29  */
  30 
  31 /*
  32  * Generic font related data and functions shared by early boot console
  33  * in dboot, kernel startup and full kernel.
  34  */
  35 #include <sys/types.h>
  36 #include <sys/systm.h>
  37 #include <sys/tem_impl.h>
  38 #include <sys/font.h>
  39 #include <sys/sysmacros.h>
  40 
  41 /*
  42  * To simplify my life, I am "temporarily" collecting the commonly used
  43  * color bits here. The bits shared between loader, dboot, early boot, tem.
  44  * This data would need some sort of API, but I am in no condition to figure
  45  * something out right now.
  46  */
  47 
  48 /* ANSI color to sun color translation. */
  49 /* BEGIN CSTYLED */
  50 /*                            Bk  Rd  Gr  Br  Bl  Mg  Cy  Wh */
  51 const uint8_t dim_xlate[] = {  1,  5,  3,  7,  2,  6,  4,  8 };
  52 const uint8_t brt_xlate[] = {  9, 13, 11, 15, 10, 14, 12,  0 };
  53 
  54 /* The pc color here is actually referring to standard 16 color VGA map. */
  55 const uint8_t solaris_color_to_pc_color[16] = {
  56     15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
  57 };
  58 
  59 /* 4-bit to 24-bit color translation. */
  60 const text_cmap_t cmap4_to_24 = {
  61 /* 0    1    2    3    4    5    6    7    8    9   10   11   12   13   14   15
  62   Wh+  Bk   Bl   Gr   Cy   Rd   Mg   Br   Wh   Bk+  Bl+  Gr+  Cy+  Rd+  Mg+  Yw */
  63   .red = {
  64  0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff
  65 },
  66   .green = {
  67  0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff
  68 },
  69   .blue = {
  70  0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00
  71 }
  72 };
  73 /* END CSTYLED */
  74 
  75 /*
  76  * Fonts are statically linked with this module. At some point an
  77  * RFE might be desireable to allow dynamic font loading.  The
  78  * original intention to facilitate dynamic fonts can be seen
  79  * by examining the data structures and set_font().  As much of
  80  * the original code is retained but modified to be suited for
  81  * traversing a list of static fonts.
  82  */
  83 
  84 /*
  85  * Must be sorted by font size in descending order
  86  */
  87 font_list_t fonts = STAILQ_HEAD_INITIALIZER(fonts);






  88 
  89 bitmap_data_t *
  90 set_font(short *rows, short *cols, short height, short width)
  91 {
  92         bitmap_data_t *font = NULL;
  93         struct fontlist *fl;

  94 
  95         /*
  96          * First check for manually loaded font.
  97          */
  98         STAILQ_FOREACH(fl, &fonts, font_next) {
  99                 if (fl->font_flags == FONT_MANUAL ||
 100                     fl->font_flags == FONT_BOOT) {
 101                         font = fl->font_data;
 102                         if (font->font == NULL && fl->font_load != NULL &&
 103                             fl->font_name != NULL) {
 104                                 font = fl->font_load(fl->font_name);
 105                         }
 106                         if (font == NULL || font->font == NULL)
 107                                 font = NULL;
 108                         break;
 109                 }
 110         }
 111 
 112         if (font != NULL) {
 113                 *rows = (height - BORDER_PIXELS) / font->height;
 114                 *cols = (width - BORDER_PIXELS) / font->width;
 115                 return (font);
 116         }
 117 
 118         /*
 119          * Find best font for these dimensions, or use default
 120          *
 121          * A 1 pixel border is the absolute minimum we could have
 122          * as a border around the text window (BORDER_PIXELS = 2),
 123          * however a slightly larger border not only looks better
 124          * but for the fonts currently statically built into the
 125          * emulator causes much better font selection for the
 126          * normal range of screen resolutions.
 127          */
 128         STAILQ_FOREACH(fl, &fonts, font_next) {
 129                 font = fl->font_data;
 130                 if ((((*rows * font->height) + BORDER_PIXELS) <= height) &&
 131                     (((*cols * font->width) + BORDER_PIXELS) <= width)) {
 132                         if (font->font == NULL) {
 133                                 if (fl->font_load != NULL &&
 134                                     fl->font_name != NULL) {
 135                                         font = fl->font_load(fl->font_name);
 136                                 }
 137                                 if (font == NULL)
 138                                         continue;
 139                         }
 140                         *rows = (height - BORDER_PIXELS) / font->height;
 141                         *cols = (width - BORDER_PIXELS) / font->width;
 142                         break;
 143                 }
 144                 font = NULL;
 145         }
 146 
 147         if (font == NULL) {
 148                 /*
 149                  * We have fonts sorted smallest last, try it before
 150                  * falling back to builtin.
 151                  */
 152                 fl = STAILQ_LAST(&fonts, fontlist, font_next);
 153                 if (fl != NULL && fl->font_load != NULL &&
 154                     fl->font_name != NULL) {
 155                         font = fl->font_load(fl->font_name);

 156                 }
 157                 if (font == NULL)
 158                         font = &DEFAULT_FONT_DATA;
 159 
 160                 *rows = (height - BORDER_PIXELS) / font->height;
 161                 *cols = (width - BORDER_PIXELS) / font->width;
 162         }
 163 
 164         return (font);
 165 }
 166 
 167 /* Binary search for the glyph. Return 0 if not found. */
 168 static uint16_t
 169 font_bisearch(const struct font_map *map, uint32_t len, uint32_t src)
 170 {
 171         int min, mid, max;
 172 
 173         min = 0;
 174         max = len - 1;
 175 
 176         /* Empty font map. */
 177         if (len == 0)
 178                 return (0);
 179         /* Character below minimal entry. */
 180         if (src < map[0].font_src)
 181                 return (0);
 182         /* Optimization: ASCII characters occur very often. */
 183         if (src <= map[0].font_src + map[0].font_len)
 184                 return (src - map[0].font_src + map[0].font_dst);
 185         /* Character above maximum entry. */
 186         if (src > map[max].font_src + map[max].font_len)
 187                 return (0);
 188 
 189         /* Binary search. */
 190         while (max >= min) {
 191                 mid = (min + max) / 2;
 192                 if (src < map[mid].font_src)
 193                         max = mid - 1;
 194                 else if (src > map[mid].font_src + map[mid].font_len)
 195                         min = mid + 1;
 196                 else
 197                         return (src - map[mid].font_src + map[mid].font_dst);
 198         }
 199 
 200         return (0);
 201 }
 202 
 203 /*
 204  * Return glyph bitmap. If glyph is not found, we will return bitmap
 205  * for the first (offset 0) glyph.
 206  */
 207 const uint8_t *
 208 font_lookup(const struct font *vf, uint32_t c)
 209 {
 210         uint32_t src;
 211         uint16_t dst;
 212         size_t stride;
 213 
 214         src = TEM_CHAR(c);
 215 
 216         /* Substitute bold with normal if not found. */
 217         if (TEM_CHAR_ATTR(c) & TEM_ATTR_BOLD) {
 218                 dst = font_bisearch(vf->vf_map[VFNT_MAP_BOLD],
 219                     vf->vf_map_count[VFNT_MAP_BOLD], src);
 220                 if (dst != 0)
 221                         goto found;
 222         }
 223         dst = font_bisearch(vf->vf_map[VFNT_MAP_NORMAL],
 224             vf->vf_map_count[VFNT_MAP_NORMAL], src);
 225 
 226 found:
 227         stride = howmany(vf->vf_width, 8) * vf->vf_height;
 228         return (&vf->vf_bytes[dst * stride]);
 229 }
 230 
 231 /*
 232  * bit_to_pix4 is for 4-bit frame buffers.  It will write one output byte
 233  * for each 2 bits of input bitmap.  It inverts the input bits before
 234  * doing the output translation, for reverse video.
 235  *
 236  * Assuming foreground is 0001 and background is 0000...
 237  * An input data byte of 0x53 will output the bit pattern
 238  * 00000001 00000001 00000000 00010001.
 239  */
 240 
 241 void
 242 font_bit_to_pix4(
 243     struct font *f,
 244     uint8_t *dest,
 245     uint32_t c,
 246     uint8_t fg_color,
 247     uint8_t bg_color)
 248 {
 249         int     row;
 250         int     byte;
 251         int     i;
 252         const uint8_t *cp;
 253         uint8_t data;
 254         uint8_t nibblett;
 255         int     bytes_wide;
 256 
 257         cp = font_lookup(f, c);
 258         bytes_wide = (f->vf_width + 7) / 8;
 259 
 260         for (row = 0; row < f->vf_height; row++) {
 261                 for (byte = 0; byte < bytes_wide; byte++) {
 262                         data = *cp++;
 263                         for (i = 0; i < 4; i++) {
 264                                 nibblett = (data >> ((3-i) * 2)) & 0x3;
 265                                 switch (nibblett) {
 266                                 case 0x0:
 267                                         *dest++ = bg_color << 4 | bg_color;
 268                                         break;
 269                                 case 0x1:
 270                                         *dest++ = bg_color << 4 | fg_color;
 271                                         break;
 272                                 case 0x2:
 273                                         *dest++ = fg_color << 4 | bg_color;
 274                                         break;
 275                                 case 0x3:
 276                                         *dest++ = fg_color << 4 | fg_color;
 277                                         break;
 278                                 }
 279                         }
 280                 }
 281         }
 282 }
 283 
 284 /*
 285  * bit_to_pix8 is for 8-bit frame buffers.  It will write one output byte
 286  * for each bit of input bitmap.  It inverts the input bits before
 287  * doing the output translation, for reverse video.
 288  *
 289  * Assuming foreground is 00000001 and background is 00000000...
 290  * An input data byte of 0x53 will output the bit pattern
 291  * 0000000 000000001 00000000 00000001 00000000 00000000 00000001 00000001.
 292  */
 293 
 294 void
 295 font_bit_to_pix8(
 296     struct font *f,
 297     uint8_t *dest,
 298     uint32_t c,
 299     uint8_t fg_color,
 300     uint8_t bg_color)
 301 {
 302         int     row;
 303         int     byte;
 304         int     i;
 305         const uint8_t *cp;
 306         uint8_t data;
 307         int     bytes_wide;
 308         uint8_t mask;
 309         int     bitsleft, nbits;
 310 
 311         cp = font_lookup(f, c);
 312         bytes_wide = (f->vf_width + 7) / 8;
 313 
 314         for (row = 0; row < f->vf_height; row++) {
 315                 bitsleft = f->vf_width;
 316                 for (byte = 0; byte < bytes_wide; byte++) {
 317                         data = *cp++;
 318                         mask = 0x80;
 319                         nbits = MIN(8, bitsleft);
 320                         bitsleft -= nbits;
 321                         for (i = 0; i < nbits; i++) {
 322                                 *dest++ = (data & mask ? fg_color: bg_color);
 323                                 mask = mask >> 1;
 324                         }
 325                 }
 326         }
 327 }
 328 
 329 /*
 330  * bit_to_pix16 is for 16-bit frame buffers.  It will write two output bytes
 331  * for each bit of input bitmap.  It inverts the input bits before
 332  * doing the output translation, for reverse video.
 333  *
 334  * Assuming foreground is 11111111 11111111
 335  * and background is 00000000 00000000
 336  * An input data byte of 0x53 will output the bit pattern
 337  *
 338  * 00000000 00000000
 339  * 11111111 11111111
 340  * 00000000 00000000
 341  * 11111111 11111111
 342  * 00000000 00000000
 343  * 00000000 00000000
 344  * 11111111 11111111
 345  * 11111111 11111111
 346  *
 347  */
 348 
 349 void
 350 font_bit_to_pix16(
 351     struct font *f,
 352     uint16_t *dest,
 353     uint32_t c,
 354     uint16_t fg_color16,
 355     uint16_t bg_color16)
 356 {
 357         int     row;
 358         int     byte;
 359         int     i;
 360         const uint8_t   *cp;
 361         uint16_t data, d;
 362         int     bytes_wide;
 363         int     bitsleft, nbits;
 364 
 365         cp = font_lookup(f, c);
 366         bytes_wide = (f->vf_width + 7) / 8;
 367 
 368         for (row = 0; row < f->vf_height; row++) {
 369                 bitsleft = f->vf_width;
 370                 for (byte = 0; byte < bytes_wide; byte++) {
 371                         data = *cp++;
 372                         nbits = MIN(8, bitsleft);
 373                         bitsleft -= nbits;
 374                         for (i = 0; i < nbits; i++) {
 375                                 d = ((data << i) & 0x80 ?
 376                                     fg_color16 : bg_color16);
 377                                 *dest++ = d;
 378                         }
 379                 }
 380         }
 381 }
 382 
 383 /*
 384  * bit_to_pix24 is for 24-bit frame buffers.  It will write three output bytes
 385  * for each bit of input bitmap.  It inverts the input bits before
 386  * doing the output translation, for reverse video.
 387  *
 388  * Assuming foreground is 11111111 11111111 11111111
 389  * and background is 00000000 00000000 00000000
 390  * An input data byte of 0x53 will output the bit pattern
 391  *
 392  * 00000000 00000000 00000000
 393  * 11111111 11111111 11111111
 394  * 00000000 00000000 00000000
 395  * 11111111 11111111 11111111
 396  * 00000000 00000000 00000000
 397  * 00000000 00000000 00000000
 398  * 11111111 11111111 11111111
 399  * 11111111 11111111 11111111
 400  *
 401  */
 402 
 403 void
 404 font_bit_to_pix24(
 405     struct font *f,
 406     uint8_t *dest,
 407     uint32_t c,
 408     uint32_t fg_color32,
 409     uint32_t bg_color32)
 410 {
 411         int     row;
 412         int     byte;
 413         int     i;
 414         const uint8_t   *cp;
 415         uint32_t data, d;
 416         int     bytes_wide;
 417         int     bitsleft, nbits;
 418 
 419         cp = font_lookup(f, c);
 420         bytes_wide = (f->vf_width + 7) / 8;
 421 
 422         for (row = 0; row < f->vf_height; row++) {
 423                 bitsleft = f->vf_width;
 424                 for (byte = 0; byte < bytes_wide; byte++) {
 425                         data = *cp++;
 426                         nbits = MIN(8, bitsleft);
 427                         bitsleft -= nbits;
 428                         for (i = 0; i < nbits; i++) {
 429                                 d = ((data << i) & 0x80 ?
 430                                     fg_color32 : bg_color32);
 431                                 *dest++ = d & 0xff;
 432                                 *dest++ = (d >> 8) & 0xff;
 433                                 *dest++ = (d >> 16) & 0xff;
 434                         }
 435                 }
 436         }
 437 }
 438 
 439 /*
 440  * bit_to_pix32 is for 32-bit frame buffers.  It will write four output bytes
 441  * for each bit of input bitmap.  It inverts the input bits before
 442  * doing the output translation, for reverse video.  Note that each
 443  * 24-bit RGB value is finally stored in a 32-bit unsigned int, with the
 444  * high-order byte set to zero.
 445  *
 446  * Assuming foreground is 00000000 11111111 11111111 11111111
 447  * and background is 00000000 00000000 00000000 00000000
 448  * An input data byte of 0x53 will output the bit pattern
 449  *
 450  * 00000000 00000000 00000000 00000000
 451  * 00000000 11111111 11111111 11111111
 452  * 00000000 00000000 00000000 00000000
 453  * 00000000 11111111 11111111 11111111
 454  * 00000000 00000000 00000000 00000000
 455  * 00000000 00000000 00000000 00000000
 456  * 00000000 11111111 11111111 11111111
 457  * 00000000 11111111 11111111 11111111
 458  *
 459  */
 460 
 461 void
 462 font_bit_to_pix32(
 463     struct font *f,
 464     uint32_t *dest,
 465     uint32_t c,
 466     uint32_t fg_color32,
 467     uint32_t bg_color32)
 468 {
 469         int     row;
 470         int     byte;
 471         int     i;
 472         const uint8_t *cp, *ul;
 473         uint32_t data;
 474         int     bytes_wide;
 475         int     bitsleft, nbits;
 476 
 477         if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE)
 478                 ul = font_lookup(f, 0x0332);    /* combining low line */
 479         else
 480                 ul = NULL;
 481 
 482         cp = font_lookup(f, c);
 483         bytes_wide = (f->vf_width + 7) / 8;
 484 
 485         for (row = 0; row < f->vf_height; row++) {
 486                 bitsleft = f->vf_width;
 487                 for (byte = 0; byte < bytes_wide; byte++) {
 488                         if (ul == NULL)
 489                                 data = *cp++;
 490                         else
 491                                 data = *cp++ | *ul++;
 492                         nbits = MIN(8, bitsleft);
 493                         bitsleft -= nbits;
 494                         for (i = 0; i < nbits; i++) {
 495                                 *dest++ = ((data << i) & 0x80 ?
 496                                     fg_color32 : bg_color32);
 497                         }
 498                 }
 499         }
 500 }