1 #include <sys/ansi.h> 2 #include <sys/io.h> 3 #include <fs.h> 4 #include <bios.h> 5 #include <com32.h> 6 #include <graphics.h> 7 #include <syslinux/memscan.h> 8 #include <syslinux/firmware.h> 9 #include <syslinux/video.h> 10 11 #include <sys/vesa/vesa.h> 12 #include <sys/vesa/video.h> 13 #include <sys/vesa/debug.h> 14 #include <minmax.h> 15 #include "core.h" 16 17 __export struct firmware *firmware = NULL; 18 19 extern struct ansi_ops bios_ansi_ops; 20 21 #define BIOS_CURXY ((struct curxy *)0x450) /* Array for each page */ 22 #define BIOS_ROWS (*(uint8_t *)0x484) /* Minus one; if zero use 24 (= 25 lines) */ 23 #define BIOS_COLS (*(uint16_t *)0x44A) 24 #define BIOS_PAGE (*(uint8_t *)0x462) 25 26 static void bios_text_mode(void) 27 { 28 syslinux_force_text_mode(); 29 } 30 31 static void bios_get_mode(int *cols, int *rows) 32 { 33 *rows = BIOS_ROWS ? BIOS_ROWS + 1 : 25; 34 *cols = BIOS_COLS; 35 } 36 37 static uint16_t cursor_type; /* Saved cursor pattern */ 38 39 static void bios_get_cursor(uint8_t *x, uint8_t *y) 40 { 41 com32sys_t ireg, oreg; 42 43 memset(&ireg, 0, sizeof(ireg)); 44 45 ireg.eax.b[1] = 0x03; 46 ireg.ebx.b[1] = BIOS_PAGE; 47 __intcall(0x10, &ireg, &oreg); 48 cursor_type = oreg.ecx.w[0]; 49 *x = oreg.edx.b[0]; 50 *y = oreg.edx.b[1]; 51 } 52 53 static void bios_erase(int x0, int y0, int x1, int y1, uint8_t attribute) 54 { 55 static com32sys_t ireg; 56 memset(&ireg, 0, sizeof(ireg)); 57 58 ireg.eax.w[0] = 0x0600; /* Clear window */ 59 ireg.ebx.b[1] = attribute; 60 ireg.ecx.b[0] = x0; 61 ireg.ecx.b[1] = y0; 62 ireg.edx.b[0] = x1; 63 ireg.edx.b[1] = y1; 64 __intcall(0x10, &ireg, NULL); 65 } 66 67 static void bios_showcursor(const struct term_state *st) 68 { 69 static com32sys_t ireg; 70 uint16_t cursor = st->cursor ? cursor_type : 0x2020; 71 72 memset(&ireg, 0, sizeof(ireg)); 73 74 ireg.eax.b[1] = 0x01; 75 ireg.ecx.w[0] = cursor; 76 __intcall(0x10, &ireg, NULL); 77 } 78 79 static void bios_set_cursor(int x, int y, bool visible) 80 { 81 const int page = BIOS_PAGE; 82 struct curxy xy = BIOS_CURXY[page]; 83 static com32sys_t ireg; 84 85 memset(&ireg, 0, sizeof(ireg)); 86 87 (void)visible; 88 89 if (xy.x != x || xy.y != y) { 90 ireg.eax.b[1] = 0x02; 91 ireg.ebx.b[1] = page; 92 ireg.edx.b[1] = y; 93 ireg.edx.b[0] = x; 94 __intcall(0x10, &ireg, NULL); 95 } 96 } 97 98 static void bios_write_char(uint8_t ch, uint8_t attribute) 99 { 100 static com32sys_t ireg; 101 102 memset(&ireg, 0, sizeof(ireg)); 103 104 ireg.eax.b[1] = 0x09; 105 ireg.eax.b[0] = ch; 106 ireg.ebx.b[1] = BIOS_PAGE; 107 ireg.ebx.b[0] = attribute; 108 ireg.ecx.w[0] = 1; 109 __intcall(0x10, &ireg, NULL); 110 } 111 112 static void bios_scroll_up(uint8_t cols, uint8_t rows, uint8_t attribute) 113 { 114 static com32sys_t ireg; 115 116 memset(&ireg, 0, sizeof(ireg)); 117 118 ireg.eax.w[0] = 0x0601; 119 ireg.ebx.b[1] = attribute; 120 ireg.ecx.w[0] = 0; 121 ireg.edx.b[1] = rows; 122 ireg.edx.b[0] = cols; 123 __intcall(0x10, &ireg, NULL); /* Scroll */ 124 } 125 126 static void bios_beep(void) 127 { 128 static com32sys_t ireg; 129 130 memset(&ireg, 0, sizeof(ireg)); 131 132 ireg.eax.w[0] = 0x0e07; 133 ireg.ebx.b[1] = BIOS_PAGE; 134 __intcall(0x10, &ireg, NULL); 135 } 136 137 struct output_ops bios_output_ops = { 138 .erase = bios_erase, 139 .write_char = bios_write_char, 140 .showcursor = bios_showcursor, 141 .set_cursor = bios_set_cursor, 142 .scroll_up = bios_scroll_up, 143 .beep = bios_beep, 144 .get_mode = bios_get_mode, 145 .text_mode = bios_text_mode, 146 .get_cursor = bios_get_cursor, 147 }; 148 149 extern char bios_getchar(char *); 150 extern int bios_pollchar(void); 151 extern uint8_t bios_shiftflags(void); 152 153 struct input_ops bios_input_ops = { 154 .getchar = bios_getchar, 155 .pollchar = bios_pollchar, 156 .shiftflags = bios_shiftflags, 157 }; 158 159 static void bios_get_serial_console_info(uint16_t *iobase, uint16_t *divisor, 160 uint16_t *flowctl) 161 { 162 *iobase = SerialPort; 163 *divisor = BaudDivisor; 164 165 *flowctl = FlowOutput | FlowInput | (FlowIgnore << 4); 166 167 if (!DisplayCon) 168 *flowctl |= (0x80 << 8); 169 } 170 171 void bios_adv_init(void) 172 { 173 static com32sys_t reg; 174 175 memset(®, 0, sizeof(reg)); 176 call16(adv_init, ®, NULL); 177 } 178 179 int bios_adv_write(void) 180 { 181 static com32sys_t reg; 182 183 memset(®, 0, sizeof(reg)); 184 call16(adv_write, ®, ®); 185 return (reg.eflags.l & EFLAGS_CF) ? -1 : 0; 186 } 187 188 struct adv_ops bios_adv_ops = { 189 .init = bios_adv_init, 190 .write = bios_adv_write, 191 }; 192 193 194 static int __constfunc is_power_of_2(unsigned int x) 195 { 196 return x && !(x & (x - 1)); 197 } 198 199 static int vesacon_paged_mode_ok(const struct vesa_mode_info *mi) 200 { 201 int i; 202 203 if (!is_power_of_2(mi->win_size) || 204 !is_power_of_2(mi->win_grain) || mi->win_grain > mi->win_size) 205 return 0; /* Impossible... */ 206 207 for (i = 0; i < 2; i++) { 208 if ((mi->win_attr[i] & 0x05) == 0x05 && mi->win_seg[i]) 209 return 1; /* Usable window */ 210 } 211 212 return 0; /* Nope... */ 213 } 214 215 static int bios_vesacon_set_mode(struct vesa_info *vesa_info, int *px, int *py, 216 enum vesa_pixel_format *bestpxf) 217 { 218 com32sys_t rm; 219 uint16_t mode, bestmode, *mode_ptr; 220 struct vesa_info *vi; 221 struct vesa_general_info *gi; 222 struct vesa_mode_info *mi; 223 enum vesa_pixel_format pxf; 224 int x = *px, y = *py; 225 int err = 0; 226 227 /* Allocate space in the bounce buffer for these structures */ 228 vi = lzalloc(sizeof *vi); 229 if (!vi) { 230 err = 10; /* Out of memory */ 231 goto exit; 232 } 233 gi = &vi->gi; 234 mi = &vi->mi; 235 236 memset(&rm, 0, sizeof rm); 237 238 gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */ 239 rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ 240 rm.edi.w[0] = OFFS(gi); 241 rm.es = SEG(gi); 242 __intcall(0x10, &rm, &rm); 243 244 if (rm.eax.w[0] != 0x004F) { 245 err = 1; /* Function call failed */ 246 goto exit; 247 } 248 if (gi->signature != VESA_MAGIC) { 249 err = 2; /* No magic */ 250 goto exit; 251 } 252 if (gi->version < 0x0102) { 253 err = 3; /* VESA 1.2+ required */ 254 goto exit; 255 } 256 257 /* Copy general info */ 258 memcpy(&vesa_info->gi, gi, sizeof *gi); 259 260 /* Search for the proper mode with a suitable color and memory model... */ 261 262 mode_ptr = GET_PTR(gi->video_mode_ptr); 263 bestmode = 0; 264 *bestpxf = PXF_NONE; 265 266 while ((mode = *mode_ptr++) != 0xFFFF) { 267 mode &= 0x1FF; /* The rest are attributes of sorts */ 268 269 debug("Found mode: 0x%04x\r\n", mode); 270 271 memset(&rm, 0, sizeof rm); 272 memset(mi, 0, sizeof *mi); 273 rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ 274 rm.ecx.w[0] = mode; 275 rm.edi.w[0] = OFFS(mi); 276 rm.es = SEG(mi); 277 __intcall(0x10, &rm, &rm); 278 279 /* Must be a supported mode */ 280 if (rm.eax.w[0] != 0x004f) 281 continue; 282 283 debug 284 ("mode_attr 0x%04x, h_res = %4d, v_res = %4d, bpp = %2d, layout = %d (%d,%d,%d)\r\n", 285 mi->mode_attr, mi->h_res, mi->v_res, mi->bpp, mi->memory_layout, 286 mi->rpos, mi->gpos, mi->bpos); 287 288 /* Must be an LFB color graphics mode supported by the hardware. 289 290 The bits tested are: 291 4 - graphics mode 292 3 - color mode 293 1 - mode information available (mandatory in VBE 1.2+) 294 0 - mode supported by hardware 295 */ 296 if ((mi->mode_attr & 0x001b) != 0x001b) 297 continue; 298 299 /* Must be the chosen size */ 300 if (mi->h_res != x || mi->v_res != y) 301 continue; 302 303 /* We don't support multibank (interlaced memory) modes */ 304 /* 305 * Note: The Bochs VESA BIOS (vbe.c 1.58 2006/08/19) violates the 306 * specification which states that banks == 1 for unbanked modes; 307 * fortunately it does report bank_size == 0 for those. 308 */ 309 if (mi->banks > 1 && mi->bank_size) { 310 debug("bad: banks = %d, banksize = %d, pages = %d\r\n", 311 mi->banks, mi->bank_size, mi->image_pages); 312 continue; 313 } 314 315 /* Must be either a flat-framebuffer mode, or be an acceptable 316 paged mode */ 317 if (!(mi->mode_attr & 0x0080) && !vesacon_paged_mode_ok(mi)) { 318 debug("bad: invalid paged mode\r\n"); 319 continue; 320 } 321 322 /* Must either be a packed-pixel mode or a direct color mode 323 (depending on VESA version ); must be a supported pixel format */ 324 pxf = PXF_NONE; /* Not usable */ 325 326 if (mi->bpp == 32 && 327 (mi->memory_layout == 4 || 328 (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 && 329 mi->bpos == 0))) 330 pxf = PXF_BGRA32; 331 else if (mi->bpp == 24 && 332 (mi->memory_layout == 4 || 333 (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 && 334 mi->bpos == 0))) 335 pxf = PXF_BGR24; 336 else if (mi->bpp == 16 && 337 (mi->memory_layout == 4 || 338 (mi->memory_layout == 6 && mi->rpos == 11 && mi->gpos == 5 && 339 mi->bpos == 0))) 340 pxf = PXF_LE_RGB16_565; 341 else if (mi->bpp == 15 && 342 (mi->memory_layout == 4 || 343 (mi->memory_layout == 6 && mi->rpos == 10 && mi->gpos == 5 && 344 mi->bpos == 0))) 345 pxf = PXF_LE_RGB15_555; 346 347 if (pxf < *bestpxf) { 348 debug("Best mode so far, pxf = %d\r\n", pxf); 349 350 /* Best mode so far... */ 351 bestmode = mode; 352 *bestpxf = pxf; 353 354 /* Copy mode info */ 355 memcpy(&vesa_info->mi, mi, sizeof *mi); 356 } 357 } 358 359 if (*bestpxf == PXF_NONE) { 360 err = 4; /* No mode found */ 361 goto exit; 362 } 363 364 mi = &vesa_info->mi; 365 mode = bestmode; 366 367 memset(&rm, 0, sizeof rm); 368 /* Now set video mode */ 369 rm.eax.w[0] = 0x4F02; /* Set SVGA video mode */ 370 if (mi->mode_attr & 0x0080) 371 mode |= 0x4000; /* Request linear framebuffer if supported */ 372 rm.ebx.w[0] = mode; 373 __intcall(0x10, &rm, &rm); 374 if (rm.eax.w[0] != 0x004F) { 375 err = 9; /* Failed to set mode */ 376 goto exit; 377 } 378 379 exit: 380 if (vi) 381 lfree(vi); 382 383 return err; 384 } 385 386 static void set_window_pos(struct win_info *wi, size_t win_pos) 387 { 388 static com32sys_t ireg; 389 390 wi->win_pos = win_pos; 391 392 if (wi->win_num < 0) 393 return; /* This should never happen... */ 394 395 memset(&ireg, 0, sizeof ireg); 396 ireg.eax.w[0] = 0x4F05; 397 ireg.ebx.b[0] = wi->win_num; 398 ireg.edx.w[0] = win_pos >> wi->win_gshift; 399 400 __intcall(0x10, &ireg, NULL); 401 } 402 403 static void bios_vesacon_screencpy(size_t dst, const uint32_t * src, 404 size_t bytes, struct win_info *wi) 405 { 406 size_t win_pos, win_off; 407 size_t win_size = wi->win_size; 408 size_t omask = win_size - 1; 409 char *win_base = wi->win_base; 410 const char *s = (const char *)src; 411 size_t l; 412 413 while (bytes) { 414 win_off = dst & omask; 415 win_pos = dst & ~omask; 416 417 if (__unlikely(win_pos != wi->win_pos)) 418 set_window_pos(wi, win_pos); 419 420 l = min(bytes, win_size - win_off); 421 memcpy(win_base + win_off, s, l); 422 423 bytes -= l; 424 s += l; 425 dst += l; 426 } 427 } 428 429 static int bios_font_query(uint8_t **font) 430 { 431 com32sys_t rm; 432 433 /* Get BIOS 8x16 font */ 434 435 memset(&rm, 0, sizeof rm); 436 437 rm.eax.w[0] = 0x1130; /* Get Font Information */ 438 rm.ebx.w[0] = 0x0600; /* Get 8x16 ROM font */ 439 __intcall(0x10, &rm, &rm); 440 *font = MK_PTR(rm.es, rm.ebp.w[0]); 441 442 return 16; 443 444 } 445 struct vesa_ops bios_vesa_ops = { 446 .set_mode = bios_vesacon_set_mode, 447 .screencpy = bios_vesacon_screencpy, 448 .font_query = bios_font_query, 449 }; 450 451 static uint32_t min_lowmem_heap = 65536; 452 extern char __lowmem_heap[]; 453 uint8_t KbdFlags; /* Check for keyboard escapes */ 454 __export uint8_t KbdMap[256]; /* Keyboard map */ 455 456 __export uint16_t PXERetry; 457 458 static inline void check_escapes(void) 459 { 460 com32sys_t ireg, oreg; 461 462 memset(&ireg, 0, sizeof ireg); 463 ireg.eax.b[1] = 0x02; /* Check keyboard flags */ 464 __intcall(0x16, &ireg, &oreg); 465 466 KbdFlags = oreg.eax.b[0]; 467 468 /* Ctrl->skip 386 check */ 469 if (!(oreg.eax.b[0] & 0x04)) { 470 /* 471 * Now check that there is sufficient low (DOS) memory 472 * 473 * NOTE: Linux doesn't use all of real_mode_seg, but we use 474 * the same segment for COMBOOT images, which can use all 64K. 475 */ 476 uint32_t mem; 477 478 __intcall(0x12, &ireg, &oreg); 479 480 mem = ((uint32_t)__lowmem_heap) + min_lowmem_heap + 1023; 481 mem = mem >> 10; 482 483 if (oreg.eax.w[0] < mem) { 484 char buf[256]; 485 486 snprintf(buf, sizeof(buf), 487 "It appears your computer has only " 488 "%dK of low (\"DOS\") RAM.\n" 489 "This version of Syslinux needs " 490 "%dK to boot. " 491 "If you get this\nmessage in error, " 492 "hold down the Ctrl key while booting, " 493 "and I\nwill take your word for it.\n", 494 oreg.eax.w[0], mem); 495 writestr(buf); 496 kaboom(); 497 } 498 } 499 } 500 501 extern uint32_t BIOS_timer_next; 502 extern uint32_t timer_irq; 503 static inline void bios_timer_init(void) 504 { 505 unsigned long next; 506 uint32_t *hook = (uint32_t *)BIOS_timer_hook; 507 508 next = *hook; 509 BIOS_timer_next = next; 510 *hook = (uint32_t)&timer_irq; 511 } 512 513 extern uint16_t *bios_free_mem; 514 515 struct e820_entry { 516 uint64_t start; 517 uint64_t len; 518 uint32_t type; 519 }; 520 521 static int bios_scan_memory(scan_memory_callback_t callback, void *data) 522 { 523 static com32sys_t ireg; 524 com32sys_t oreg; 525 struct e820_entry *e820buf; 526 uint64_t start, len, maxlen; 527 int memfound = 0; 528 int rv; 529 addr_t dosmem; 530 const addr_t bios_data = 0x510; /* Amount to reserve for BIOS data */ 531 532 /* Use INT 12h to get DOS memory */ 533 __intcall(0x12, &__com32_zero_regs, &oreg); 534 dosmem = oreg.eax.w[0] << 10; 535 if (dosmem < 32 * 1024 || dosmem > 640 * 1024) { 536 /* INT 12h reports nonsense... now what? */ 537 uint16_t ebda_seg = *(uint16_t *) 0x40e; 538 if (ebda_seg >= 0x8000 && ebda_seg < 0xa000) 539 dosmem = ebda_seg << 4; 540 else 541 dosmem = 640 * 1024; /* Hope for the best... */ 542 } 543 rv = callback(data, bios_data, dosmem - bios_data, SMT_FREE); 544 if (rv) 545 return rv; 546 547 /* First try INT 15h AX=E820h */ 548 e820buf = lzalloc(sizeof *e820buf); 549 if (!e820buf) 550 return -1; 551 552 memset(&ireg, 0, sizeof ireg); 553 ireg.eax.l = 0xe820; 554 ireg.edx.l = 0x534d4150; 555 ireg.ebx.l = 0; 556 ireg.ecx.l = sizeof(*e820buf); 557 ireg.es = SEG(e820buf); 558 ireg.edi.w[0] = OFFS(e820buf); 559 560 do { 561 __intcall(0x15, &ireg, &oreg); 562 563 if ((oreg.eflags.l & EFLAGS_CF) || 564 (oreg.eax.l != 0x534d4150) || (oreg.ecx.l < 20)) 565 break; 566 567 start = e820buf->start; 568 len = e820buf->len; 569 570 if (start < 0x100000000ULL) { 571 /* Don't rely on E820 being valid for low memory. Doing so 572 could mean stuff like overwriting the PXE stack even when 573 using "keeppxe", etc. */ 574 if (start < 0x100000ULL) { 575 if (len > 0x100000ULL - start) 576 len -= 0x100000ULL - start; 577 else 578 len = 0; 579 start = 0x100000ULL; 580 } 581 582 maxlen = 0x100000000ULL - start; 583 if (len > maxlen) 584 len = maxlen; 585 586 if (len) { 587 enum syslinux_memmap_types type; 588 589 type = e820buf->type == 1 ? SMT_FREE : SMT_RESERVED; 590 rv = callback(data, (addr_t) start, (addr_t) len, type); 591 if (rv) 592 return rv; 593 memfound = 1; 594 } 595 } 596 597 ireg.ebx.l = oreg.ebx.l; 598 } while (oreg.ebx.l); 599 600 lfree(e820buf); 601 602 if (memfound) 603 return 0; 604 605 /* Next try INT 15h AX=E801h */ 606 memset(&ireg, 0, sizeof ireg); 607 ireg.eax.w[0] = 0xe801; 608 __intcall(0x15, &ireg, &oreg); 609 610 if (!(oreg.eflags.l & EFLAGS_CF) && oreg.ecx.w[0]) { 611 rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, SMT_FREE); 612 if (rv) 613 return rv; 614 615 if (oreg.edx.w[0]) { 616 rv = callback(data, (addr_t) 16 << 20, 617 oreg.edx.w[0] << 16, SMT_FREE); 618 if (rv) 619 return rv; 620 } 621 622 return 0; 623 } 624 625 /* Finally try INT 15h AH=88h */ 626 memset(&ireg, 0, sizeof ireg); 627 ireg.eax.w[0] = 0x8800; 628 __intcall(0x15, &ireg, &oreg); 629 if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.w[0]) { 630 rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, SMT_FREE); 631 if (rv) 632 return rv; 633 } 634 635 return 0; 636 } 637 638 static struct syslinux_memscan bios_memscan = { 639 .func = bios_scan_memory, 640 }; 641 642 void bios_init(void) 643 { 644 int i; 645 646 /* Initialize timer */ 647 bios_timer_init(); 648 649 for (i = 0; i < 256; i++) 650 KbdMap[i] = i; 651 652 bios_adjust_screen(); 653 654 /* Init the memory subsystem */ 655 bios_free_mem = (uint16_t *)0x413; 656 syslinux_memscan_add(&bios_memscan); 657 mem_init(); 658 659 dprintf("%s%s", syslinux_banner, copyright_str); 660 661 /* CPU-dependent initialization and related checks. */ 662 check_escapes(); 663 664 /* 665 * Scan the DMI tables for interesting information. 666 */ 667 dmi_init(); 668 } 669 670 extern void bios_timer_cleanup(void); 671 672 extern uint32_t OrigFDCTabPtr; 673 674 static void bios_cleanup_hardware(void) 675 { 676 /* Restore the original pointer to the floppy descriptor table */ 677 if (OrigFDCTabPtr) 678 *((uint32_t *)(4 * 0x1e)) = OrigFDCTabPtr; 679 680 /* 681 * Linux wants the floppy motor shut off before starting the 682 * kernel, at least bootsect.S seems to imply so. If we don't 683 * load the floppy driver, this is *definitely* so! 684 */ 685 __intcall(0x13, &zero_regs, NULL); 686 687 call16(bios_timer_cleanup, &zero_regs, NULL); 688 689 /* If we enabled serial port interrupts, clean them up now */ 690 sirq_cleanup(); 691 } 692 693 extern void *bios_malloc(size_t, enum heap, size_t); 694 extern void *bios_realloc(void *, size_t); 695 extern void bios_free(void *); 696 697 struct mem_ops bios_mem_ops = { 698 .malloc = bios_malloc, 699 .realloc = bios_realloc, 700 .free = bios_free, 701 }; 702 703 struct firmware bios_fw = { 704 .init = bios_init, 705 .adjust_screen = bios_adjust_screen, 706 .cleanup = bios_cleanup_hardware, 707 .disk_init = bios_disk_init, 708 .o_ops = &bios_output_ops, 709 .i_ops = &bios_input_ops, 710 .get_serial_console_info = bios_get_serial_console_info, 711 .adv_ops = &bios_adv_ops, 712 .vesa = &bios_vesa_ops, 713 .mem = &bios_mem_ops, 714 }; 715 716 void syslinux_register_bios(void) 717 { 718 firmware = &bios_fw; 719 } 720