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/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 typedef enum pc_colors { 56 pc_black = 0, 57 pc_blue = 1, 58 pc_green = 2, 59 pc_cyan = 3, 60 pc_red = 4, 61 pc_magenta = 5, 62 pc_brown = 6, 63 pc_white = 7, 64 pc_grey = 8, 65 pc_brt_blue = 9, 66 pc_brt_green = 10, 67 pc_brt_cyan = 11, 68 pc_brt_red = 12, 69 pc_brt_magenta = 13, 70 pc_yellow = 14, 71 pc_brt_white = 15 72 } pc_colors_t; 73 74 const uint8_t solaris_color_to_pc_color[16] = { 75 pc_brt_white, /* 0 - brt_white */ 76 pc_black, /* 1 - black */ 77 pc_blue, /* 2 - blue */ 78 pc_green, /* 3 - green */ 79 pc_cyan, /* 4 - cyan */ 80 pc_red, /* 5 - red */ 81 pc_magenta, /* 6 - magenta */ 82 pc_brown, /* 7 - brown */ 83 pc_white, /* 8 - white */ 84 pc_grey, /* 9 - gery */ 85 pc_brt_blue, /* 10 - brt_blue */ 86 pc_brt_green, /* 11 - brt_green */ 87 pc_brt_cyan, /* 12 - brt_cyan */ 88 pc_brt_red, /* 13 - brt_red */ 89 pc_brt_magenta, /* 14 - brt_magenta */ 90 pc_yellow /* 15 - yellow */ 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 /* 110 * Fonts are statically linked with this module. At some point an 111 * RFE might be desireable to allow dynamic font loading. The 112 * original intention to facilitate dynamic fonts can be seen 113 * by examining the data structures and set_font(). As much of 114 * the original code is retained but modified to be suited for 115 * traversing a list of static fonts. 116 */ 117 118 /* 119 * Must be sorted by font size in descending order 120 */ 121 font_list_t fonts = STAILQ_HEAD_INITIALIZER(fonts); 122 123 bitmap_data_t * 124 set_font(short *rows, short *cols, short h, short w) 125 { 126 bitmap_data_t *font = NULL; 127 struct fontlist *fl; 128 unsigned height = h; 129 unsigned width = w; 130 131 /* 132 * First check for manually loaded font. 133 */ 134 STAILQ_FOREACH(fl, &fonts, font_next) { 135 if (fl->font_flags == FONT_MANUAL || 136 fl->font_flags == FONT_BOOT) { 137 font = fl->font_data; 138 if (font->font == NULL && fl->font_load != NULL && 139 fl->font_name != NULL) { 140 font = fl->font_load(fl->font_name); 141 } 142 if (font == NULL || font->font == NULL) 143 font = NULL; 144 break; 145 } 146 } 147 148 if (font != NULL) { 149 *rows = (height - BORDER_PIXELS) / font->height; 150 *cols = (width - BORDER_PIXELS) / font->width; 151 return (font); 152 } 153 154 /* 155 * Find best font for these dimensions, or use default 156 * 157 * A 1 pixel border is the absolute minimum we could have 158 * as a border around the text window (BORDER_PIXELS = 2), 159 * however a slightly larger border not only looks better 160 * but for the fonts currently statically built into the 161 * emulator causes much better font selection for the 162 * normal range of screen resolutions. 163 */ 164 STAILQ_FOREACH(fl, &fonts, font_next) { 165 font = fl->font_data; 166 if ((((*rows * font->height) + BORDER_PIXELS) <= height) && 167 (((*cols * font->width) + BORDER_PIXELS) <= width)) { 168 if (font->font == NULL) { 169 if (fl->font_load != NULL && 170 fl->font_name != NULL) { 171 font = fl->font_load(fl->font_name); 172 } 173 if (font == NULL) 174 continue; 175 } 176 *rows = (height - BORDER_PIXELS) / font->height; 177 *cols = (width - BORDER_PIXELS) / font->width; 178 break; 179 } 180 font = NULL; 181 } 182 183 if (font == NULL) { 184 /* 185 * We have fonts sorted smallest last, try it before 186 * falling back to builtin. 187 */ 188 fl = STAILQ_LAST(&fonts, fontlist, font_next); 189 if (fl != NULL && fl->font_load != NULL && 190 fl->font_name != NULL) { 191 font = fl->font_load(fl->font_name); 192 } 193 if (font == NULL) 194 font = &DEFAULT_FONT_DATA; 195 196 *rows = (height - BORDER_PIXELS) / font->height; 197 *cols = (width - BORDER_PIXELS) / font->width; 198 } 199 200 return (font); 201 } 202 203 /* Binary search for the glyph. Return 0 if not found. */ 204 static uint16_t 205 font_bisearch(const struct font_map *map, uint32_t len, uint32_t src) 206 { 207 unsigned min, mid, max; 208 209 min = 0; 210 max = len - 1; 211 212 /* Empty font map. */ 213 if (len == 0) 214 return (0); 215 /* Character below minimal entry. */ 216 if (src < map[0].font_src) 217 return (0); 218 /* Optimization: ASCII characters occur very often. */ 219 if (src <= map[0].font_src + map[0].font_len) 220 return (src - map[0].font_src + map[0].font_dst); 221 /* Character above maximum entry. */ 222 if (src > map[max].font_src + map[max].font_len) 223 return (0); 224 225 /* Binary search. */ 226 while (max >= min) { 227 mid = (min + max) / 2; 228 if (src < map[mid].font_src) 229 max = mid - 1; 230 else if (src > map[mid].font_src + map[mid].font_len) 231 min = mid + 1; 232 else 233 return (src - map[mid].font_src + map[mid].font_dst); 234 } 235 236 return (0); 237 } 238 239 /* 240 * Return glyph bitmap. If glyph is not found, we will return bitmap 241 * for the first (offset 0) glyph. 242 */ 243 const uint8_t * 244 font_lookup(const struct font *vf, uint32_t c) 245 { 246 uint32_t src; 247 uint16_t dst; 248 size_t stride; 249 250 src = TEM_CHAR(c); 251 252 /* Substitute bold with normal if not found. */ 253 if (TEM_CHAR_ATTR(c) & TEM_ATTR_BOLD) { 254 dst = font_bisearch(vf->vf_map[VFNT_MAP_BOLD], 255 vf->vf_map_count[VFNT_MAP_BOLD], src); 256 if (dst != 0) 257 goto found; 258 } 259 dst = font_bisearch(vf->vf_map[VFNT_MAP_NORMAL], 260 vf->vf_map_count[VFNT_MAP_NORMAL], src); 261 262 found: 263 stride = howmany(vf->vf_width, 8) * vf->vf_height; 264 return (&vf->vf_bytes[dst * stride]); 265 } 266 267 /* 268 * bit_to_pix4 is for 4-bit frame buffers. It will write one output byte 269 * for each 2 bits of input bitmap. It inverts the input bits before 270 * doing the output translation, for reverse video. 271 * 272 * Assuming foreground is 0001 and background is 0000... 273 * An input data byte of 0x53 will output the bit pattern 274 * 00000001 00000001 00000000 00010001. 275 */ 276 277 void 278 font_bit_to_pix4( 279 struct font *f, 280 uint8_t *dest, 281 uint32_t c, 282 uint8_t fg_color, 283 uint8_t bg_color) 284 { 285 uint32_t row; 286 int byte; 287 int i; 288 const uint8_t *cp, *ul; 289 uint8_t data; 290 uint8_t nibblett; 291 int bytes_wide; 292 293 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 294 ul = font_lookup(f, 0x0332); /* combining low line */ 295 else 296 ul = NULL; 297 298 cp = font_lookup(f, c); 299 bytes_wide = (f->vf_width + 7) / 8; 300 301 for (row = 0; row < f->vf_height; row++) { 302 for (byte = 0; byte < bytes_wide; byte++) { 303 if (ul == NULL) 304 data = *cp++; 305 else 306 data = *cp++ | *ul++; 307 for (i = 0; i < 4; i++) { 308 nibblett = (data >> ((3-i) * 2)) & 0x3; 309 switch (nibblett) { 310 case 0x0: 311 *dest++ = bg_color << 4 | bg_color; 312 break; 313 case 0x1: 314 *dest++ = bg_color << 4 | fg_color; 315 break; 316 case 0x2: 317 *dest++ = fg_color << 4 | bg_color; 318 break; 319 case 0x3: 320 *dest++ = fg_color << 4 | fg_color; 321 break; 322 } 323 } 324 } 325 } 326 } 327 328 /* 329 * bit_to_pix8 is for 8-bit frame buffers. It will write one output byte 330 * for each bit of input bitmap. It inverts the input bits before 331 * doing the output translation, for reverse video. 332 * 333 * Assuming foreground is 00000001 and background is 00000000... 334 * An input data byte of 0x53 will output the bit pattern 335 * 0000000 000000001 00000000 00000001 00000000 00000000 00000001 00000001. 336 */ 337 338 void 339 font_bit_to_pix8( 340 struct font *f, 341 uint8_t *dest, 342 uint32_t c, 343 uint8_t fg_color, 344 uint8_t bg_color) 345 { 346 uint32_t row; 347 int byte; 348 int i; 349 const uint8_t *cp, *ul; 350 uint8_t data; 351 int bytes_wide; 352 uint8_t mask; 353 int bitsleft, nbits; 354 355 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 356 ul = font_lookup(f, 0x0332); /* combining low line */ 357 else 358 ul = NULL; 359 360 cp = font_lookup(f, c); 361 bytes_wide = (f->vf_width + 7) / 8; 362 363 for (row = 0; row < f->vf_height; row++) { 364 bitsleft = f->vf_width; 365 for (byte = 0; byte < bytes_wide; byte++) { 366 if (ul == NULL) 367 data = *cp++; 368 else 369 data = *cp++ | *ul++; 370 mask = 0x80; 371 nbits = MIN(8, bitsleft); 372 bitsleft -= nbits; 373 for (i = 0; i < nbits; i++) { 374 *dest++ = (data & mask ? fg_color: bg_color); 375 mask = mask >> 1; 376 } 377 } 378 } 379 } 380 381 /* 382 * bit_to_pix16 is for 16-bit frame buffers. It will write two output bytes 383 * for each bit of input bitmap. It inverts the input bits before 384 * doing the output translation, for reverse video. 385 * 386 * Assuming foreground is 11111111 11111111 387 * and background is 00000000 00000000 388 * An input data byte of 0x53 will output the bit pattern 389 * 390 * 00000000 00000000 391 * 11111111 11111111 392 * 00000000 00000000 393 * 11111111 11111111 394 * 00000000 00000000 395 * 00000000 00000000 396 * 11111111 11111111 397 * 11111111 11111111 398 * 399 */ 400 401 void 402 font_bit_to_pix16( 403 struct font *f, 404 uint16_t *dest, 405 uint32_t c, 406 uint16_t fg_color16, 407 uint16_t bg_color16) 408 { 409 uint32_t row; 410 int byte; 411 int i; 412 const uint8_t *cp, *ul; 413 uint16_t data, d; 414 int bytes_wide; 415 int bitsleft, nbits; 416 417 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 418 ul = font_lookup(f, 0x0332); /* combining low line */ 419 else 420 ul = NULL; 421 422 cp = font_lookup(f, c); 423 bytes_wide = (f->vf_width + 7) / 8; 424 425 for (row = 0; row < f->vf_height; row++) { 426 bitsleft = f->vf_width; 427 for (byte = 0; byte < bytes_wide; byte++) { 428 if (ul == NULL) 429 data = *cp++; 430 else 431 data = *cp++ | *ul++; 432 nbits = MIN(8, bitsleft); 433 bitsleft -= nbits; 434 for (i = 0; i < nbits; i++) { 435 d = ((data << i) & 0x80 ? 436 fg_color16 : bg_color16); 437 *dest++ = d; 438 } 439 } 440 } 441 } 442 443 /* 444 * bit_to_pix24 is for 24-bit frame buffers. It will write three output bytes 445 * for each bit of input bitmap. It inverts the input bits before 446 * doing the output translation, for reverse video. 447 * 448 * Assuming foreground is 11111111 11111111 11111111 449 * and background is 00000000 00000000 00000000 450 * An input data byte of 0x53 will output the bit pattern 451 * 452 * 00000000 00000000 00000000 453 * 11111111 11111111 11111111 454 * 00000000 00000000 00000000 455 * 11111111 11111111 11111111 456 * 00000000 00000000 00000000 457 * 00000000 00000000 00000000 458 * 11111111 11111111 11111111 459 * 11111111 11111111 11111111 460 * 461 */ 462 463 void 464 font_bit_to_pix24( 465 struct font *f, 466 uint8_t *dest, 467 uint32_t c, 468 uint32_t fg_color32, 469 uint32_t bg_color32) 470 { 471 uint32_t row; 472 int byte; 473 int i; 474 const uint8_t *cp, *ul; 475 uint32_t data, d; 476 int bytes_wide; 477 int bitsleft, nbits; 478 479 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 480 ul = font_lookup(f, 0x0332); /* combining low line */ 481 else 482 ul = NULL; 483 484 cp = font_lookup(f, c); 485 bytes_wide = (f->vf_width + 7) / 8; 486 487 for (row = 0; row < f->vf_height; row++) { 488 bitsleft = f->vf_width; 489 for (byte = 0; byte < bytes_wide; byte++) { 490 if (ul == NULL) 491 data = *cp++; 492 else 493 data = *cp++ | *ul++; 494 495 nbits = MIN(8, bitsleft); 496 bitsleft -= nbits; 497 for (i = 0; i < nbits; i++) { 498 d = ((data << i) & 0x80 ? 499 fg_color32 : bg_color32); 500 *dest++ = d & 0xff; 501 *dest++ = (d >> 8) & 0xff; 502 *dest++ = (d >> 16) & 0xff; 503 } 504 } 505 } 506 } 507 508 /* 509 * bit_to_pix32 is for 32-bit frame buffers. It will write four output bytes 510 * for each bit of input bitmap. It inverts the input bits before 511 * doing the output translation, for reverse video. Note that each 512 * 24-bit RGB value is finally stored in a 32-bit unsigned int, with the 513 * high-order byte set to zero. 514 * 515 * Assuming foreground is 00000000 11111111 11111111 11111111 516 * and background is 00000000 00000000 00000000 00000000 517 * An input data byte of 0x53 will output the bit pattern 518 * 519 * 00000000 00000000 00000000 00000000 520 * 00000000 11111111 11111111 11111111 521 * 00000000 00000000 00000000 00000000 522 * 00000000 11111111 11111111 11111111 523 * 00000000 00000000 00000000 00000000 524 * 00000000 00000000 00000000 00000000 525 * 00000000 11111111 11111111 11111111 526 * 00000000 11111111 11111111 11111111 527 * 528 */ 529 530 void 531 font_bit_to_pix32( 532 struct font *f, 533 uint32_t *dest, 534 uint32_t c, 535 uint32_t fg_color32, 536 uint32_t bg_color32) 537 { 538 uint32_t row; 539 int byte; 540 int i; 541 const uint8_t *cp, *ul; 542 uint32_t data; 543 int bytes_wide; 544 int bitsleft, nbits; 545 546 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 547 ul = font_lookup(f, 0x0332); /* combining low line */ 548 else 549 ul = NULL; 550 551 cp = font_lookup(f, c); 552 bytes_wide = (f->vf_width + 7) / 8; 553 554 for (row = 0; row < f->vf_height; row++) { 555 bitsleft = f->vf_width; 556 for (byte = 0; byte < bytes_wide; byte++) { 557 if (ul == NULL) 558 data = *cp++; 559 else 560 data = *cp++ | *ul++; 561 nbits = MIN(8, bitsleft); 562 bitsleft -= nbits; 563 for (i = 0; i < nbits; i++) { 564 *dest++ = ((data << i) & 0x80 ? 565 fg_color32 : bg_color32); 566 } 567 } 568 } 569 } 570