1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 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/rgb.h> 39 #include <sys/font.h> 40 #include <sys/sysmacros.h> 41 42 /* 43 * To simplify my life, I am "temporarily" collecting the commonly used 44 * color bits here. The bits shared between loader, dboot, early boot, tem. 45 * This data would need some sort of API, but I am in no condition to figure 46 * something out right now. 47 */ 48 49 /* ANSI color to sun color translation. */ 50 /* BEGIN CSTYLED */ 51 /* Bk Rd Gr Br Bl Mg Cy Wh */ 52 const uint8_t dim_xlate[XLATE_NCOLORS] = { 1, 5, 3, 7, 2, 6, 4, 8 }; 53 const uint8_t brt_xlate[XLATE_NCOLORS] = { 9, 13, 11, 15, 10, 14, 12, 0 }; 54 55 const uint8_t solaris_color_to_pc_color[16] = { 56 pc_brt_white, /* 0 - brt_white */ 57 pc_black, /* 1 - black */ 58 pc_blue, /* 2 - blue */ 59 pc_green, /* 3 - green */ 60 pc_cyan, /* 4 - cyan */ 61 pc_red, /* 5 - red */ 62 pc_magenta, /* 6 - magenta */ 63 pc_brown, /* 7 - brown */ 64 pc_white, /* 8 - white */ 65 pc_grey, /* 9 - grey */ 66 pc_brt_blue, /* 10 - brt_blue */ 67 pc_brt_green, /* 11 - brt_green */ 68 pc_brt_cyan, /* 12 - brt_cyan */ 69 pc_brt_red, /* 13 - brt_red */ 70 pc_brt_magenta, /* 14 - brt_magenta */ 71 pc_yellow /* 15 - yellow */ 72 }; 73 74 const uint8_t pc_color_to_solaris_color[16] = { 75 sun_black, /* 0 - black */ 76 sun_blue, /* 1 - blue */ 77 sun_green, /* 2 - green */ 78 sun_cyan, /* 3 - cyan */ 79 sun_red, /* 4 - red */ 80 sun_magenta, /* 5 - magenta */ 81 sun_brown, /* 6 - brown */ 82 sun_white, /* 7 - white */ 83 sun_grey, /* 8 - grey */ 84 sun_brt_blue, /* 9 - brt_blue */ 85 sun_brt_green, /* 10 - brt_green */ 86 sun_brt_cyan, /* 11 - brt_cyan */ 87 sun_brt_red, /* 12 - brt_red */ 88 sun_brt_magenta, /* 13 - brt_magenta */ 89 sun_yellow, /* 14 - yellow */ 90 sun_brt_white /* 15 - brt_white */ 91 }; 92 93 /* 4-bit to 24-bit color translation. */ 94 const text_cmap_t cmap4_to_24 = { 95 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 96 Wh+ Bk Bl Gr Cy Rd Mg Br Wh Bk+ Bl+ Gr+ Cy+ Rd+ Mg+ Yw */ 97 .red = { 98 0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff 99 }, 100 .green = { 101 0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff 102 }, 103 .blue = { 104 0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00 105 } 106 }; 107 /* END CSTYLED */ 108 109 static uint32_t 110 rgb_to_color(const rgb_t *rgb, uint32_t r, uint32_t g, uint32_t b) 111 { 112 uint32_t color; 113 int pos, size; 114 115 pos = rgb->red.pos; 116 size = rgb->red.size; 117 color = ((r * ((1 << size) - 1)) / 0xff) << pos; 118 119 pos = rgb->green.pos; 120 size = rgb->green.size; 121 color |= (((g * ((1 << size) - 1)) / 0xff) << pos); 122 123 pos = rgb->blue.pos; 124 size = rgb->blue.size; 125 color |= (((b * ((1 << size) - 1)) / 0xff) << pos); 126 127 return (color); 128 } 129 130 uint32_t 131 rgb_color_map(const rgb_t *rgb, uint8_t index) 132 { 133 uint32_t color, code, gray, level; 134 135 if (index < 16) { 136 color = rgb_to_color(rgb, cmap4_to_24.red[index], 137 cmap4_to_24.green[index], cmap4_to_24.blue[index]); 138 return (color); 139 } 140 141 /* 6x6x6 color cube */ 142 if (index > 15 && index < 232) { 143 uint32_t red, green, blue; 144 145 for (red = 0; red < 6; red++) { 146 for (green = 0; green < 6; green++) { 147 for (blue = 0; blue < 6; blue++) { 148 code = 16 + (red * 36) + 149 (green * 6) + blue; 150 if (code != index) 151 continue; 152 red = red ? (red * 40 + 55) : 0; 153 green = green ? (green * 40 + 55) : 0; 154 blue = blue ? (blue * 40 + 55) : 0; 155 color = rgb_to_color(rgb, red, green, 156 blue); 157 return (color); 158 } 159 } 160 } 161 } 162 163 /* colors 232-255 are a grayscale ramp */ 164 for (gray = 0; gray < 24; gray++) { 165 level = (gray * 10) + 8; 166 code = 232 + gray; 167 if (code == index) 168 break; 169 } 170 return (rgb_to_color(rgb, level, level, level)); 171 } 172 /* 173 * Fonts are statically linked with this module. At some point an 174 * RFE might be desireable to allow dynamic font loading. The 175 * original intention to facilitate dynamic fonts can be seen 176 * by examining the data structures and set_font(). As much of 177 * the original code is retained but modified to be suited for 178 * traversing a list of static fonts. 179 */ 180 181 /* 182 * Must be sorted by font size in descending order 183 */ 184 font_list_t fonts = STAILQ_HEAD_INITIALIZER(fonts); 185 186 /* 187 * Reset font flags to FONT_AUTO. 188 */ 189 void 190 reset_font_flags(void) 191 { 192 struct fontlist *fl; 193 194 STAILQ_FOREACH(fl, &fonts, font_next) { 195 fl->font_flags = FONT_AUTO; 196 } 197 } 198 199 __weak_symbol bitmap_data_t * 200 gfx_get_font(void) 201 { 202 return (NULL); 203 } 204 205 bitmap_data_t * 206 set_font(short *rows, short *cols, short h, short w) 207 { 208 bitmap_data_t *font = NULL; 209 struct fontlist *fl; 210 unsigned height = h; 211 unsigned width = w; 212 213 /* 214 * First check for manually loaded font. 215 */ 216 STAILQ_FOREACH(fl, &fonts, font_next) { 217 if (fl->font_flags == FONT_MANUAL || 218 fl->font_flags == FONT_BOOT) { 219 font = fl->font_data; 220 if (font->font == NULL && fl->font_load != NULL && 221 fl->font_name != NULL) { 222 font = fl->font_load(fl->font_name); 223 } 224 if (font == NULL || font->font == NULL) 225 font = NULL; 226 break; 227 } 228 } 229 230 if (font == NULL) 231 font = gfx_get_font(); 232 233 if (font != NULL) { 234 *rows = (height - BORDER_PIXELS) / font->height; 235 *cols = (width - BORDER_PIXELS) / font->width; 236 return (font); 237 } 238 239 /* 240 * Find best font for these dimensions, or use default 241 * 242 * A 1 pixel border is the absolute minimum we could have 243 * as a border around the text window (BORDER_PIXELS = 2), 244 * however a slightly larger border not only looks better 245 * but for the fonts currently statically built into the 246 * emulator causes much better font selection for the 247 * normal range of screen resolutions. 248 */ 249 STAILQ_FOREACH(fl, &fonts, font_next) { 250 font = fl->font_data; 251 if ((((*rows * font->height) + BORDER_PIXELS) <= height) && 252 (((*cols * font->width) + BORDER_PIXELS) <= width)) { 253 if (font->font == NULL || 254 fl->font_flags == FONT_RELOAD) { 255 if (fl->font_load != NULL && 256 fl->font_name != NULL) { 257 font = fl->font_load(fl->font_name); 258 } 259 if (font == NULL) 260 continue; 261 } 262 *rows = (height - BORDER_PIXELS) / font->height; 263 *cols = (width - BORDER_PIXELS) / font->width; 264 break; 265 } 266 font = NULL; 267 } 268 269 if (font == NULL) { 270 /* 271 * We have fonts sorted smallest last, try it before 272 * falling back to builtin. 273 */ 274 fl = STAILQ_LAST(&fonts, fontlist, font_next); 275 if (fl != NULL && fl->font_load != NULL && 276 fl->font_name != NULL) { 277 font = fl->font_load(fl->font_name); 278 } 279 if (font == NULL) 280 font = &DEFAULT_FONT_DATA; 281 282 *rows = (height - BORDER_PIXELS) / font->height; 283 *cols = (width - BORDER_PIXELS) / font->width; 284 } 285 286 return (font); 287 } 288 289 /* Binary search for the glyph. Return 0 if not found. */ 290 static uint16_t 291 font_bisearch(const struct font_map *map, uint32_t len, uint32_t src) 292 { 293 unsigned min, mid, max; 294 295 min = 0; 296 max = len - 1; 297 298 /* Empty font map. */ 299 if (len == 0) 300 return (0); 301 /* Character below minimal entry. */ 302 if (src < map[0].font_src) 303 return (0); 304 /* Optimization: ASCII characters occur very often. */ 305 if (src <= map[0].font_src + map[0].font_len) 306 return (src - map[0].font_src + map[0].font_dst); 307 /* Character above maximum entry. */ 308 if (src > map[max].font_src + map[max].font_len) 309 return (0); 310 311 /* Binary search. */ 312 while (max >= min) { 313 mid = (min + max) / 2; 314 if (src < map[mid].font_src) 315 max = mid - 1; 316 else if (src > map[mid].font_src + map[mid].font_len) 317 min = mid + 1; 318 else 319 return (src - map[mid].font_src + map[mid].font_dst); 320 } 321 322 return (0); 323 } 324 325 /* 326 * Return glyph bitmap. If glyph is not found, we will return bitmap 327 * for the first (offset 0) glyph. 328 */ 329 const uint8_t * 330 font_lookup(const struct font *vf, uint32_t c) 331 { 332 uint32_t src; 333 uint16_t dst; 334 size_t stride; 335 336 src = TEM_CHAR(c); 337 338 /* Substitute bold with normal if not found. */ 339 if (TEM_CHAR_ATTR(c) & TEM_ATTR_BOLD) { 340 dst = font_bisearch(vf->vf_map[VFNT_MAP_BOLD], 341 vf->vf_map_count[VFNT_MAP_BOLD], src); 342 if (dst != 0) 343 goto found; 344 } 345 dst = font_bisearch(vf->vf_map[VFNT_MAP_NORMAL], 346 vf->vf_map_count[VFNT_MAP_NORMAL], src); 347 348 found: 349 stride = howmany(vf->vf_width, 8) * vf->vf_height; 350 return (&vf->vf_bytes[dst * stride]); 351 } 352 353 /* 354 * bit_to_pix4 is for 4-bit frame buffers. It will write one output byte 355 * for each 2 bits of input bitmap. It inverts the input bits before 356 * doing the output translation, for reverse video. 357 * 358 * Assuming foreground is 0001 and background is 0000... 359 * An input data byte of 0x53 will output the bit pattern 360 * 00000001 00000001 00000000 00010001. 361 */ 362 363 void 364 font_bit_to_pix4( 365 struct font *f, 366 uint8_t *dest, 367 uint32_t c, 368 uint8_t fg_color, 369 uint8_t bg_color) 370 { 371 uint32_t row; 372 int byte; 373 int i; 374 const uint8_t *cp, *ul; 375 uint8_t data; 376 uint8_t nibblett; 377 int bytes_wide; 378 379 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 380 ul = font_lookup(f, 0x0332); /* combining low line */ 381 else 382 ul = NULL; 383 384 cp = font_lookup(f, c); 385 bytes_wide = (f->vf_width + 7) / 8; 386 387 for (row = 0; row < f->vf_height; row++) { 388 for (byte = 0; byte < bytes_wide; byte++) { 389 if (ul == NULL) 390 data = *cp++; 391 else 392 data = *cp++ | *ul++; 393 for (i = 0; i < 4; i++) { 394 nibblett = (data >> ((3-i) * 2)) & 0x3; 395 switch (nibblett) { 396 case 0x0: 397 *dest++ = bg_color << 4 | bg_color; 398 break; 399 case 0x1: 400 *dest++ = bg_color << 4 | fg_color; 401 break; 402 case 0x2: 403 *dest++ = fg_color << 4 | bg_color; 404 break; 405 case 0x3: 406 *dest++ = fg_color << 4 | fg_color; 407 break; 408 } 409 } 410 } 411 } 412 } 413 414 /* 415 * bit_to_pix8 is for 8-bit frame buffers. It will write one output byte 416 * for each bit of input bitmap. It inverts the input bits before 417 * doing the output translation, for reverse video. 418 * 419 * Assuming foreground is 00000001 and background is 00000000... 420 * An input data byte of 0x53 will output the bit pattern 421 * 0000000 000000001 00000000 00000001 00000000 00000000 00000001 00000001. 422 */ 423 424 void 425 font_bit_to_pix8( 426 struct font *f, 427 uint8_t *dest, 428 uint32_t c, 429 uint8_t fg_color, 430 uint8_t bg_color) 431 { 432 uint32_t row; 433 int byte; 434 int i; 435 const uint8_t *cp, *ul; 436 uint8_t data; 437 int bytes_wide; 438 uint8_t mask; 439 int bitsleft, nbits; 440 441 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 442 ul = font_lookup(f, 0x0332); /* combining low line */ 443 else 444 ul = NULL; 445 446 cp = font_lookup(f, c); 447 bytes_wide = (f->vf_width + 7) / 8; 448 449 for (row = 0; row < f->vf_height; row++) { 450 bitsleft = f->vf_width; 451 for (byte = 0; byte < bytes_wide; byte++) { 452 if (ul == NULL) 453 data = *cp++; 454 else 455 data = *cp++ | *ul++; 456 mask = 0x80; 457 nbits = MIN(8, bitsleft); 458 bitsleft -= nbits; 459 for (i = 0; i < nbits; i++) { 460 *dest++ = (data & mask ? fg_color: bg_color); 461 mask = mask >> 1; 462 } 463 } 464 } 465 } 466 467 /* 468 * bit_to_pix16 is for 16-bit frame buffers. It will write two output bytes 469 * for each bit of input bitmap. It inverts the input bits before 470 * doing the output translation, for reverse video. 471 * 472 * Assuming foreground is 11111111 11111111 473 * and background is 00000000 00000000 474 * An input data byte of 0x53 will output the bit pattern 475 * 476 * 00000000 00000000 477 * 11111111 11111111 478 * 00000000 00000000 479 * 11111111 11111111 480 * 00000000 00000000 481 * 00000000 00000000 482 * 11111111 11111111 483 * 11111111 11111111 484 * 485 */ 486 487 void 488 font_bit_to_pix16( 489 struct font *f, 490 uint16_t *dest, 491 uint32_t c, 492 uint16_t fg_color16, 493 uint16_t bg_color16) 494 { 495 uint32_t row; 496 int byte; 497 int i; 498 const uint8_t *cp, *ul; 499 uint16_t data, d; 500 int bytes_wide; 501 int bitsleft, nbits; 502 503 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 504 ul = font_lookup(f, 0x0332); /* combining low line */ 505 else 506 ul = NULL; 507 508 cp = font_lookup(f, c); 509 bytes_wide = (f->vf_width + 7) / 8; 510 511 for (row = 0; row < f->vf_height; row++) { 512 bitsleft = f->vf_width; 513 for (byte = 0; byte < bytes_wide; byte++) { 514 if (ul == NULL) 515 data = *cp++; 516 else 517 data = *cp++ | *ul++; 518 nbits = MIN(8, bitsleft); 519 bitsleft -= nbits; 520 for (i = 0; i < nbits; i++) { 521 d = ((data << i) & 0x80 ? 522 fg_color16 : bg_color16); 523 *dest++ = d; 524 } 525 } 526 } 527 } 528 529 /* 530 * bit_to_pix24 is for 24-bit frame buffers. It will write three output bytes 531 * for each bit of input bitmap. It inverts the input bits before 532 * doing the output translation, for reverse video. 533 * 534 * Assuming foreground is 11111111 11111111 11111111 535 * and background is 00000000 00000000 00000000 536 * An input data byte of 0x53 will output the bit pattern 537 * 538 * 00000000 00000000 00000000 539 * 11111111 11111111 11111111 540 * 00000000 00000000 00000000 541 * 11111111 11111111 11111111 542 * 00000000 00000000 00000000 543 * 00000000 00000000 00000000 544 * 11111111 11111111 11111111 545 * 11111111 11111111 11111111 546 * 547 */ 548 549 void 550 font_bit_to_pix24( 551 struct font *f, 552 uint8_t *dest, 553 uint32_t c, 554 uint32_t fg_color32, 555 uint32_t bg_color32) 556 { 557 uint32_t row; 558 int byte; 559 int i; 560 const uint8_t *cp, *ul; 561 uint32_t data, d; 562 int bytes_wide; 563 int bitsleft, nbits; 564 565 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 566 ul = font_lookup(f, 0x0332); /* combining low line */ 567 else 568 ul = NULL; 569 570 cp = font_lookup(f, c); 571 bytes_wide = (f->vf_width + 7) / 8; 572 573 for (row = 0; row < f->vf_height; row++) { 574 bitsleft = f->vf_width; 575 for (byte = 0; byte < bytes_wide; byte++) { 576 if (ul == NULL) 577 data = *cp++; 578 else 579 data = *cp++ | *ul++; 580 581 nbits = MIN(8, bitsleft); 582 bitsleft -= nbits; 583 for (i = 0; i < nbits; i++) { 584 d = ((data << i) & 0x80 ? 585 fg_color32 : bg_color32); 586 *dest++ = d & 0xff; 587 *dest++ = (d >> 8) & 0xff; 588 *dest++ = (d >> 16) & 0xff; 589 } 590 } 591 } 592 } 593 594 /* 595 * bit_to_pix32 is for 32-bit frame buffers. It will write four output bytes 596 * for each bit of input bitmap. It inverts the input bits before 597 * doing the output translation, for reverse video. Note that each 598 * 24-bit RGB value is finally stored in a 32-bit unsigned int, with the 599 * high-order byte set to zero. 600 * 601 * Assuming foreground is 00000000 11111111 11111111 11111111 602 * and background is 00000000 00000000 00000000 00000000 603 * An input data byte of 0x53 will output the bit pattern 604 * 605 * 00000000 00000000 00000000 00000000 606 * 00000000 11111111 11111111 11111111 607 * 00000000 00000000 00000000 00000000 608 * 00000000 11111111 11111111 11111111 609 * 00000000 00000000 00000000 00000000 610 * 00000000 00000000 00000000 00000000 611 * 00000000 11111111 11111111 11111111 612 * 00000000 11111111 11111111 11111111 613 * 614 */ 615 616 void 617 font_bit_to_pix32( 618 struct font *f, 619 uint32_t *dest, 620 uint32_t c, 621 uint32_t fg_color32, 622 uint32_t bg_color32) 623 { 624 uint32_t row; 625 int byte; 626 int i; 627 const uint8_t *cp, *ul; 628 uint32_t data; 629 int bytes_wide; 630 int bitsleft, nbits; 631 632 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 633 ul = font_lookup(f, 0x0332); /* combining low line */ 634 else 635 ul = NULL; 636 637 cp = font_lookup(f, c); 638 bytes_wide = (f->vf_width + 7) / 8; 639 640 for (row = 0; row < f->vf_height; row++) { 641 bitsleft = f->vf_width; 642 for (byte = 0; byte < bytes_wide; byte++) { 643 if (ul == NULL) 644 data = *cp++; 645 else 646 data = *cp++ | *ul++; 647 nbits = MIN(8, bitsleft); 648 bitsleft -= nbits; 649 for (i = 0; i < nbits; i++) { 650 *dest++ = ((data << i) & 0x80 ? 651 fg_color32 : bg_color32); 652 } 653 } 654 } 655 } 656