1 /* asmstub.c - a version of shared_src/asm.S that works under Unix */ 2 /* 3 * GRUB -- GRand Unified Bootloader 4 * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 /* Try to use glibc's transparant LFS support. */ 22 #define _LARGEFILE_SOURCE 1 23 /* lseek becomes synonymous with lseek64. */ 24 #define _FILE_OFFSET_BITS 64 25 26 /* Simulator entry point. */ 27 int grub_stage2 (void); 28 29 #include <stdlib.h> 30 #include <string.h> 31 #include <ctype.h> 32 #include <assert.h> 33 #include <stdio.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <fcntl.h> 37 #include <time.h> 38 #include <errno.h> 39 #include <string.h> 40 #include <unistd.h> 41 #include <setjmp.h> 42 #include <sys/time.h> 43 #include <termios.h> 44 #include <signal.h> 45 46 #ifdef __linux__ 47 # include <sys/ioctl.h> /* ioctl */ 48 # if !defined(__GLIBC__) || \ 49 ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))) 50 /* Maybe libc doesn't have large file support. */ 51 # include <linux/unistd.h> /* _llseek */ 52 # endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */ 53 # ifndef BLKFLSBUF 54 # define BLKFLSBUF _IO (0x12,97) /* flush buffer cache */ 55 # endif /* ! BLKFLSBUF */ 56 #endif /* __linux__ */ 57 58 /* We want to prevent any circularararity in our stubs, as well as 59 libc name clashes. */ 60 #define WITHOUT_LIBC_STUBS 1 61 #include <shared.h> 62 #include <device.h> 63 #include <serial.h> 64 #include <term.h> 65 66 /* Simulated memory sizes. */ 67 #define EXTENDED_MEMSIZE (64 * 1024 * 1024) /* 64MB */ 68 #define CONVENTIONAL_MEMSIZE (640 * 1024) /* 640kB */ 69 70 unsigned long install_partition = 0x20000; 71 unsigned long boot_drive = 0; 72 int saved_entryno = 0; 73 char version_string[] = VERSION; 74 char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */ 75 unsigned long linux_text_len = 0; 76 char *linux_data_tmp_addr = 0; 77 char *linux_data_real_addr = 0; 78 unsigned short io_map[IO_MAP_SIZE]; 79 struct apm_info apm_bios_info; 80 81 /* Emulation requirements. */ 82 char *grub_scratch_mem = 0; 83 84 struct geometry *disks = 0; 85 86 /* The map between BIOS drives and UNIX device file names. */ 87 char **device_map = 0; 88 89 /* The jump buffer for exiting correctly. */ 90 static jmp_buf env_for_exit; 91 92 /* The current color for console. */ 93 int console_current_color = A_NORMAL; 94 95 /* The file descriptor for a serial device. */ 96 static int serial_fd = -1; 97 98 /* The file name of a serial device. */ 99 static char *serial_device = 0; 100 101 #ifdef SIMULATE_SLOWNESS_OF_SERIAL 102 /* The speed of a serial device. */ 103 static unsigned int serial_speed; 104 #endif /* SIMULATE_SLOWNESS_OF_SERIAL */ 105 106 /* The main entry point into this mess. */ 107 int 108 grub_stage2 (void) 109 { 110 /* These need to be static, because they survive our stack transitions. */ 111 static int status = 0; 112 static char *realstack; 113 char *scratch, *simstack; 114 int i; 115 116 auto void doit (void); 117 118 /* We need a nested function so that we get a clean stack frame, 119 regardless of how the code is optimized. */ 120 void doit () 121 { 122 /* Make sure our stack lives in the simulated memory area. */ 123 asm volatile ("movl %%esp, %0\n\tmovl %1, %%esp\n" 124 : "=&r" (realstack) : "r" (simstack)); 125 126 /* Do a setjmp here for the stop command. */ 127 if (! setjmp (env_for_exit)) 128 { 129 /* Actually enter the generic stage2 code. */ 130 status = 0; 131 init_bios_info (); 132 } 133 else 134 { 135 /* If ERRNUM is non-zero, then set STATUS to non-zero. */ 136 if (errnum) 137 status = 1; 138 } 139 140 /* Replace our stack before we use any local variables. */ 141 asm volatile ("movl %0, %%esp\n" : : "r" (realstack)); 142 } 143 144 assert (grub_scratch_mem == 0); 145 scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15); 146 assert (scratch); 147 grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4); 148 149 /* FIXME: simulate the memory holes using mprot, if available. */ 150 151 assert (disks == 0); 152 disks = malloc (NUM_DISKS * sizeof (*disks)); 153 assert (disks); 154 /* Initialize DISKS. */ 155 for (i = 0; i < NUM_DISKS; i++) 156 disks[i].flags = -1; 157 158 if (! init_device_map (&device_map, device_map_file, floppy_disks)) 159 return 1; 160 161 /* Check some invariants. */ 162 assert ((SCRATCHSEG << 4) == SCRATCHADDR); 163 assert ((BUFFERSEG << 4) == BUFFERADDR); 164 assert (BUFFERADDR + BUFFERLEN == SCRATCHADDR); 165 assert (FSYS_BUF % 16 == 0); 166 assert (FSYS_BUF + FSYS_BUFLEN == BUFFERADDR); 167 168 #ifdef HAVE_LIBCURSES 169 /* Get into char-at-a-time mode. */ 170 if (use_curses) 171 { 172 initscr (); 173 cbreak (); 174 noecho (); 175 nonl (); 176 scrollok (stdscr, TRUE); 177 keypad (stdscr, TRUE); 178 wtimeout (stdscr, 100); 179 signal (SIGWINCH, SIG_IGN); 180 } 181 #endif 182 183 /* Make sure that actual writing is done. */ 184 sync (); 185 186 /* Set our stack, and go for it. */ 187 simstack = (char *) PROTSTACKINIT; 188 doit (); 189 190 /* I don't know if this is necessary really. */ 191 sync (); 192 193 #ifdef HAVE_LIBCURSES 194 if (use_curses) 195 endwin (); 196 #endif 197 198 /* Close off the file descriptors we used. */ 199 for (i = 0; i < NUM_DISKS; i ++) 200 if (disks[i].flags != -1) 201 { 202 #ifdef __linux__ 203 /* In Linux, invalidate the buffer cache. In other OSes, reboot 204 is one of the solutions... */ 205 ioctl (disks[i].flags, BLKFLSBUF, 0); 206 #elif defined(__sun) 207 /* FIXME */ 208 #else 209 # warning "In your operating system, the buffer cache will not be flushed." 210 #endif 211 close (disks[i].flags); 212 } 213 214 if (serial_fd >= 0) 215 close (serial_fd); 216 217 /* Release memory. */ 218 restore_device_map (device_map); 219 device_map = 0; 220 free (disks); 221 disks = 0; 222 free (scratch); 223 grub_scratch_mem = 0; 224 225 if (serial_device) 226 free (serial_device); 227 serial_device = 0; 228 229 /* Ahh... at last we're ready to return to caller. */ 230 return status; 231 } 232 233 /* Assign DRIVE to a device name DEVICE. */ 234 void 235 assign_device_name (int drive, const char *device) 236 { 237 /* If DRIVE is already assigned, free it. */ 238 if (device_map[drive]) 239 free (device_map[drive]); 240 241 /* If the old one is already opened, close it. */ 242 if (disks[drive].flags != -1) 243 { 244 close (disks[drive].flags); 245 disks[drive].flags = -1; 246 } 247 248 /* Assign DRIVE to DEVICE. */ 249 if (! device) 250 device_map[drive] = 0; 251 else 252 device_map[drive] = strdup (device); 253 } 254 255 void 256 stop (void) 257 { 258 #ifdef HAVE_LIBCURSES 259 if (use_curses) 260 endwin (); 261 #endif 262 263 /* Jump to doit. */ 264 longjmp (env_for_exit, 1); 265 } 266 267 void 268 grub_reboot (void) 269 { 270 stop (); 271 } 272 273 void 274 grub_halt (int no_apm) 275 { 276 stop (); 277 } 278 279 /* calls for direct boot-loader chaining */ 280 void 281 chain_stage1 (unsigned long segment, unsigned long offset, 282 unsigned long part_table_addr) 283 { 284 stop (); 285 } 286 287 288 void 289 chain_stage2 (unsigned long segment, unsigned long offset, int second_sector) 290 { 291 stop (); 292 } 293 294 295 /* do some funky stuff, then boot linux */ 296 void 297 linux_boot (void) 298 { 299 stop (); 300 } 301 302 303 /* For bzImage kernels. */ 304 void 305 big_linux_boot (void) 306 { 307 stop (); 308 } 309 310 311 /* booting a multiboot executable */ 312 void 313 multi_boot (int start, int mb_info) 314 { 315 stop (); 316 } 317 318 /* sets it to linear or wired A20 operation */ 319 void 320 gateA20 (int linear) 321 { 322 /* Nothing to do in the simulator. */ 323 } 324 325 /* Set up the int15 handler. */ 326 void 327 set_int15_handler (void) 328 { 329 /* Nothing to do in the simulator. */ 330 } 331 332 /* Restore the original int15 handler. */ 333 void 334 unset_int15_handler (void) 335 { 336 /* Nothing to do in the simulator. */ 337 } 338 339 /* The key map. */ 340 unsigned short bios_key_map[KEY_MAP_SIZE + 1]; 341 unsigned short ascii_key_map[KEY_MAP_SIZE + 1]; 342 343 /* Copy MAP to the drive map and set up the int13 handler. */ 344 void 345 set_int13_handler (unsigned short *map) 346 { 347 /* Nothing to do in the simulator. */ 348 } 349 350 int 351 get_code_end (void) 352 { 353 /* Just return a little area for simulation. */ 354 return BOOTSEC_LOCATION + (60 * 1024); 355 } 356 357 358 /* memory probe routines */ 359 int 360 get_memsize (int type) 361 { 362 if (! type) 363 return CONVENTIONAL_MEMSIZE >> 10; 364 else 365 return EXTENDED_MEMSIZE >> 10; 366 } 367 368 369 /* get_eisamemsize() : return packed EISA memory map, lower 16 bits is 370 * memory between 1M and 16M in 1K parts, upper 16 bits is 371 * memory above 16M in 64K parts. If error, return -1. 372 */ 373 int 374 get_eisamemsize (void) 375 { 376 return (EXTENDED_MEMSIZE >> 10); 377 } 378 379 380 #define MMAR_DESC_TYPE_AVAILABLE 1 /* available to OS */ 381 #define MMAR_DESC_TYPE_RESERVED 2 /* not available */ 382 #define MMAR_DESC_TYPE_ACPI_RECLAIM 3 /* usable by OS after reading ACPI */ 383 #define MMAR_DESC_TYPE_ACPI_NVS 4 /* required to save between NVS sessions */ 384 385 #define MMAR_DESC_LENGTH 20 386 387 /* Fetch the next entry in the memory map and return the continuation 388 value. DESC is a pointer to the descriptor buffer, and CONT is the 389 previous continuation value (0 to get the first entry in the 390 map). */ 391 int 392 get_mmap_entry (struct mmar_desc *desc, int cont) 393 { 394 /* Record the memory map statically. */ 395 static struct mmar_desc desc_table[] = 396 { 397 /* The conventional memory. */ 398 { 399 MMAR_DESC_LENGTH, 400 0, 401 CONVENTIONAL_MEMSIZE, 402 MMAR_DESC_TYPE_AVAILABLE 403 }, 404 /* BIOS RAM and ROM (such as video memory). */ 405 { 406 MMAR_DESC_LENGTH, 407 CONVENTIONAL_MEMSIZE, 408 0x100000 - CONVENTIONAL_MEMSIZE, 409 MMAR_DESC_TYPE_RESERVED 410 }, 411 /* The extended memory. */ 412 { 413 MMAR_DESC_LENGTH, 414 0x100000, 415 EXTENDED_MEMSIZE, 416 MMAR_DESC_TYPE_AVAILABLE 417 } 418 }; 419 420 int num = sizeof (desc_table) / sizeof (*desc_table); 421 422 if (cont < 0 || cont >= num) 423 { 424 /* Should not happen. */ 425 desc->desc_len = 0; 426 } 427 else 428 { 429 /* Copy the entry. */ 430 *desc = desc_table[cont++]; 431 432 /* If the next entry exists, return the index. */ 433 if (cont < num) 434 return cont; 435 } 436 437 return 0; 438 } 439 440 /* Track the int13 handler. */ 441 void 442 track_int13 (int drive) 443 { 444 /* Nothing to do in the simulator. */ 445 } 446 447 /* Get the ROM configuration table. */ 448 unsigned long 449 get_rom_config_table (void) 450 { 451 return 0; 452 } 453 454 /* Get APM BIOS information. */ 455 void 456 get_apm_info (void) 457 { 458 /* Nothing to do in the simulator. */ 459 } 460 461 /* Get VBE controller information. */ 462 int 463 get_vbe_controller_info (struct vbe_controller *controller) 464 { 465 /* Always fails. */ 466 return 0; 467 } 468 469 /* Get VBE mode information. */ 470 int 471 get_vbe_mode_info (int mode_number, struct vbe_mode *mode) 472 { 473 /* Always fails. */ 474 return 0; 475 } 476 477 /* Set VBE mode. */ 478 int 479 set_vbe_mode (int mode_number) 480 { 481 /* Always fails. */ 482 return 0; 483 } 484 485 /* low-level timing info */ 486 int 487 getrtsecs (void) 488 { 489 /* FIXME: exact value is not important, so just return time_t for now. */ 490 return time (0); 491 } 492 493 int 494 currticks (void) 495 { 496 struct timeval tv; 497 long csecs; 498 int ticks_per_csec, ticks_per_usec; 499 500 /* Note: 18.2 ticks/sec. */ 501 502 /* Get current time. */ 503 gettimeofday (&tv, 0); 504 505 /* Compute centiseconds. */ 506 csecs = tv.tv_sec / 10; 507 508 /* Ticks per centisecond. */ 509 ticks_per_csec = csecs * 182; 510 511 /* Ticks per microsecond. */ 512 ticks_per_usec = (((tv.tv_sec - csecs * 10) * 1000000 + tv.tv_usec) 513 * 182 / 10000000); 514 515 /* Sum them. */ 516 return ticks_per_csec + ticks_per_usec; 517 } 518 519 /* displays an ASCII character. IBM displays will translate some 520 characters to special graphical ones */ 521 void 522 console_putchar (int c) 523 { 524 /* Curses doesn't have VGA fonts. */ 525 switch (c) 526 { 527 case DISP_UL: 528 c = ACS_ULCORNER; 529 break; 530 case DISP_UR: 531 c = ACS_URCORNER; 532 break; 533 case DISP_LL: 534 c = ACS_LLCORNER; 535 break; 536 case DISP_LR: 537 c = ACS_LRCORNER; 538 break; 539 case DISP_HORIZ: 540 c = ACS_HLINE; 541 break; 542 case DISP_VERT: 543 c = ACS_VLINE; 544 break; 545 case DISP_LEFT: 546 c = ACS_LARROW; 547 break; 548 case DISP_RIGHT: 549 c = ACS_RARROW; 550 break; 551 case DISP_UP: 552 c = ACS_UARROW; 553 break; 554 case DISP_DOWN: 555 c = ACS_DARROW; 556 break; 557 default: 558 break; 559 } 560 561 #ifdef HAVE_LIBCURSES 562 if (use_curses) 563 { 564 /* In ncurses, a newline is treated badly, so we emulate it in our 565 own way. */ 566 if (c == '\n') 567 { 568 int x, y; 569 570 getyx (stdscr, y, x); 571 if (y + 1 == LINES) 572 scroll (stdscr); 573 else 574 move (y + 1, x); 575 } 576 else if (isprint (c)) 577 { 578 int x, y; 579 580 getyx (stdscr, y, x); 581 if (x + 1 == COLS) 582 { 583 console_putchar ('\r'); 584 console_putchar ('\n'); 585 } 586 addch (c | console_current_color); 587 } 588 else 589 { 590 addch (c); 591 } 592 593 #ifdef REFRESH_IMMEDIATELY 594 refresh (); 595 #endif 596 } 597 else 598 #endif 599 { 600 /* CR is not used in Unix. */ 601 if (c != '\r') 602 putchar (c); 603 } 604 } 605 606 /* The store for ungetch simulation. This is necessary, because 607 ncurses-1.9.9g is still used in the world and its ungetch is 608 completely broken. */ 609 #ifdef HAVE_LIBCURSES 610 static int save_char = ERR; 611 #endif 612 613 static int 614 console_translate_key (int c) 615 { 616 switch (c) 617 { 618 case KEY_LEFT: 619 return 2; 620 case KEY_RIGHT: 621 return 6; 622 case KEY_UP: 623 return 16; 624 case KEY_DOWN: 625 return 14; 626 case KEY_DC: 627 return 4; 628 case KEY_BACKSPACE: 629 return 8; 630 case KEY_HOME: 631 return 1; 632 case KEY_END: 633 return 5; 634 case KEY_PPAGE: 635 return 7; 636 case KEY_NPAGE: 637 return 3; 638 default: 639 break; 640 } 641 642 return c; 643 } 644 645 /* like 'getkey', but doesn't wait, returns -1 if nothing available */ 646 int 647 console_checkkey (void) 648 { 649 #ifdef HAVE_LIBCURSES 650 if (use_curses) 651 { 652 int c; 653 654 /* Check for SAVE_CHAR. This should not be true, because this 655 means checkkey is called twice continuously. */ 656 if (save_char != ERR) 657 return save_char; 658 659 c = getch (); 660 /* If C is not ERR, then put it back in the input queue. */ 661 if (c != ERR) 662 save_char = c; 663 return console_translate_key (c); 664 } 665 #endif 666 667 /* Just pretend they hit the space bar, then read the real key when 668 they call getkey. */ 669 return ' '; 670 } 671 672 /* returns packed BIOS/ASCII code */ 673 int 674 console_getkey (void) 675 { 676 int c; 677 678 #ifdef HAVE_LIBCURSES 679 if (use_curses) 680 { 681 /* If checkkey has already got a character, then return it. */ 682 if (save_char != ERR) 683 { 684 c = save_char; 685 save_char = ERR; 686 return console_translate_key (c); 687 } 688 689 wtimeout (stdscr, -1); 690 c = getch (); 691 wtimeout (stdscr, 100); 692 } 693 else 694 #endif 695 c = getchar (); 696 697 /* Quit if we get EOF. */ 698 if (c == -1) 699 stop (); 700 701 return console_translate_key (c); 702 } 703 704 /* returns packed values, LSB+1 is x, LSB is y */ 705 int 706 console_getxy (void) 707 { 708 int y, x; 709 #ifdef HAVE_LIBCURSES 710 if (use_curses) 711 getyx (stdscr, y, x); 712 else 713 #endif 714 y = x = 0; 715 return (x << 8) | (y & 0xff); 716 } 717 718 void 719 console_gotoxy (int x, int y) 720 { 721 #ifdef HAVE_LIBCURSES 722 if (use_curses) 723 move (y, x); 724 #endif 725 } 726 727 /* low-level character I/O */ 728 void 729 console_cls (void) 730 { 731 #ifdef HAVE_LIBCURSES 732 if (use_curses) 733 clear (); 734 #endif 735 } 736 737 void 738 console_setcolorstate (color_state state) 739 { 740 console_current_color = 741 (state == COLOR_STATE_HIGHLIGHT) ? A_REVERSE : A_NORMAL; 742 } 743 744 void 745 console_setcolor (int normal_color, int highlight_color) 746 { 747 /* Nothing to do. */ 748 } 749 750 int 751 console_setcursor (int on) 752 { 753 return 1; 754 } 755 756 /* Low-level disk I/O. Our stubbed version just returns a file 757 descriptor, not the actual geometry. */ 758 int 759 get_diskinfo (int drive, struct geometry *geometry) 760 { 761 /* FIXME: this function is truly horrid. We try opening the device, 762 then severely abuse the GEOMETRY->flags field to pass a file 763 descriptor to biosdisk. Thank God nobody's looking at this comment, 764 or my reputation would be ruined. --Gord */ 765 766 /* See if we have a cached device. */ 767 if (disks[drive].flags == -1) 768 { 769 /* The unpartitioned device name: /dev/XdX */ 770 char *devname = device_map[drive]; 771 char buf[512]; 772 773 if (! devname) 774 return -1; 775 776 if (verbose) 777 grub_printf ("Attempt to open drive 0x%x (%s)\n", 778 drive, devname); 779 780 /* Open read/write, or read-only if that failed. */ 781 if (! read_only) 782 disks[drive].flags = open (devname, O_RDWR); 783 784 if (disks[drive].flags == -1) 785 { 786 if (read_only || errno == EACCES || errno == EROFS || errno == EPERM) 787 { 788 disks[drive].flags = open (devname, O_RDONLY); 789 if (disks[drive].flags == -1) 790 { 791 assign_device_name (drive, 0); 792 return -1; 793 } 794 } 795 else 796 { 797 assign_device_name (drive, 0); 798 return -1; 799 } 800 } 801 802 /* Attempt to read the first sector. */ 803 if (read (disks[drive].flags, buf, 512) != 512) 804 { 805 close (disks[drive].flags); 806 disks[drive].flags = -1; 807 assign_device_name (drive, 0); 808 return -1; 809 } 810 811 if (disks[drive].flags != -1) 812 get_drive_geometry (&disks[drive], device_map, drive); 813 } 814 815 if (disks[drive].flags == -1) 816 return -1; 817 818 #ifdef __linux__ 819 /* In Linux, invalidate the buffer cache, so that left overs 820 from other program in the cache are flushed and seen by us */ 821 ioctl (disks[drive].flags, BLKFLSBUF, 0); 822 #endif 823 824 *geometry = disks[drive]; 825 return 0; 826 } 827 828 /* Read LEN bytes from FD in BUF. Return less than or equal to zero if an 829 error occurs, otherwise return LEN. */ 830 static int 831 nread (int fd, char *buf, size_t len) 832 { 833 int size = len; 834 835 while (len) 836 { 837 int ret = read (fd, buf, len); 838 839 if (ret <= 0) 840 { 841 if (errno == EINTR) 842 continue; 843 else 844 return ret; 845 } 846 847 len -= ret; 848 buf += ret; 849 } 850 851 return size; 852 } 853 854 /* Write LEN bytes from BUF to FD. Return less than or equal to zero if an 855 error occurs, otherwise return LEN. */ 856 static int 857 nwrite (int fd, char *buf, size_t len) 858 { 859 int size = len; 860 861 while (len) 862 { 863 int ret = write (fd, buf, len); 864 865 if (ret <= 0) 866 { 867 if (errno == EINTR) 868 continue; 869 else 870 return ret; 871 } 872 873 len -= ret; 874 buf += ret; 875 } 876 877 return size; 878 } 879 880 /* Dump BUF in the format of hexadecimal numbers. */ 881 static void 882 hex_dump (void *buf, size_t size) 883 { 884 /* FIXME: How to determine which length is readable? */ 885 #define MAX_COLUMN 70 886 887 /* use unsigned char for numerical computations */ 888 unsigned char *ptr = buf; 889 /* count the width of the line */ 890 int column = 0; 891 /* how many bytes written */ 892 int count = 0; 893 894 while (size > 0) 895 { 896 /* high 4 bits */ 897 int hi = *ptr >> 4; 898 /* low 4 bits */ 899 int low = *ptr & 0xf; 900 901 /* grub_printf does not handle prefix number, such as %2x, so 902 format the number by hand... */ 903 grub_printf ("%x%x", hi, low); 904 column += 2; 905 count++; 906 ptr++; 907 size--; 908 909 /* Insert space or newline with the interval 4 bytes. */ 910 if (size != 0 && (count % 4) == 0) 911 { 912 if (column < MAX_COLUMN) 913 { 914 grub_printf (" "); 915 column++; 916 } 917 else 918 { 919 grub_printf ("\n"); 920 column = 0; 921 } 922 } 923 } 924 925 /* Add a newline at the end for readability. */ 926 grub_printf ("\n"); 927 } 928 929 int 930 biosdisk (int subfunc, int drive, struct geometry *geometry, 931 unsigned int sector, int nsec, int segment) 932 { 933 char *buf; 934 int fd = geometry->flags; 935 936 /* Get the file pointer from the geometry, and make sure it matches. */ 937 if (fd == -1 || fd != disks[drive].flags) 938 return BIOSDISK_ERROR_GEOMETRY; 939 940 /* Seek to the specified location. */ 941 #if defined(__linux__) && (!defined(__GLIBC__) || \ 942 ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))) 943 /* Maybe libc doesn't have large file support. */ 944 { 945 loff_t offset, result; 946 static int _llseek (uint filedes, ulong hi, ulong lo, 947 loff_t *res, uint wh); 948 _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo, 949 loff_t *, res, uint, wh); 950 951 offset = (loff_t) sector * (loff_t) SECTOR_SIZE; 952 if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET)) 953 return -1; 954 } 955 #else 956 { 957 off_t offset = (off_t) sector * (off_t) SECTOR_SIZE; 958 959 if (lseek (fd, offset, SEEK_SET) != offset) 960 return -1; 961 } 962 #endif 963 964 buf = (char *) (segment << 4); 965 966 switch (subfunc) 967 { 968 case BIOSDISK_READ: 969 #ifdef __linux__ 970 if (sector == 0 && nsec > 1) 971 { 972 /* Work around a bug in linux's ez remapping. Linux remaps all 973 sectors that are read together with the MBR in one read. It 974 should only remap the MBR, so we split the read in two 975 parts. -jochen */ 976 if (nread (fd, buf, SECTOR_SIZE) != SECTOR_SIZE) 977 return -1; 978 buf += SECTOR_SIZE; 979 nsec--; 980 } 981 #endif 982 if (nread (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE) 983 return -1; 984 break; 985 986 case BIOSDISK_WRITE: 987 if (verbose) 988 { 989 grub_printf ("Write %d sectors starting from %u sector" 990 " to drive 0x%x (%s)\n", 991 nsec, sector, drive, device_map[drive]); 992 hex_dump (buf, nsec * SECTOR_SIZE); 993 } 994 if (! read_only) 995 if (nwrite (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE) 996 return -1; 997 break; 998 999 default: 1000 grub_printf ("unknown subfunc %d\n", subfunc); 1001 break; 1002 } 1003 1004 return 0; 1005 } 1006 1007 1008 void 1009 stop_floppy (void) 1010 { 1011 /* NOTUSED */ 1012 } 1013 1014 /* Fetch a key from a serial device. */ 1015 int 1016 serial_hw_fetch (void) 1017 { 1018 fd_set fds; 1019 struct timeval to; 1020 char c; 1021 1022 /* Wait only for the serial device. */ 1023 FD_ZERO (&fds); 1024 FD_SET (serial_fd, &fds); 1025 1026 to.tv_sec = 0; 1027 to.tv_usec = 0; 1028 1029 if (select (serial_fd + 1, &fds, 0, 0, &to) > 0) 1030 { 1031 if (nread (serial_fd, &c, 1) != 1) 1032 stop (); 1033 1034 return c; 1035 } 1036 1037 return -1; 1038 } 1039 1040 /* Put a character to a serial device. */ 1041 void 1042 serial_hw_put (int c) 1043 { 1044 char ch = (char) c; 1045 1046 if (nwrite (serial_fd, &ch, 1) != 1) 1047 stop (); 1048 } 1049 1050 void 1051 serial_hw_delay (void) 1052 { 1053 #ifdef SIMULATE_SLOWNESS_OF_SERIAL 1054 struct timeval otv, tv; 1055 1056 gettimeofday (&otv, 0); 1057 1058 while (1) 1059 { 1060 long delta; 1061 1062 gettimeofday (&tv, 0); 1063 delta = tv.tv_usec - otv.tv_usec; 1064 if (delta < 0) 1065 delta += 1000000; 1066 1067 if (delta >= 1000000 / (serial_speed >> 3)) 1068 break; 1069 } 1070 #endif /* SIMULATE_SLOWNESS_OF_SERIAL */ 1071 } 1072 1073 static speed_t 1074 get_termios_speed (int speed) 1075 { 1076 switch (speed) 1077 { 1078 case 2400: return B2400; 1079 case 4800: return B4800; 1080 case 9600: return B9600; 1081 case 19200: return B19200; 1082 case 38400: return B38400; 1083 #ifdef B57600 1084 case 57600: return B57600; 1085 #endif 1086 #ifdef B115200 1087 case 115200: return B115200; 1088 #endif 1089 } 1090 1091 return B0; 1092 } 1093 1094 /* Get the port number of the unit UNIT. In the grub shell, this doesn't 1095 make sense. */ 1096 unsigned short 1097 serial_hw_get_port (int unit) 1098 { 1099 return 0; 1100 } 1101 1102 /* Initialize a serial device. In the grub shell, PORT is unused. */ 1103 int 1104 serial_hw_init (unsigned short port, unsigned int speed, 1105 int word_len, int parity, int stop_bit_len) 1106 { 1107 struct termios termios; 1108 speed_t termios_speed; 1109 int i; 1110 1111 /* Check if the file name is specified. */ 1112 if (! serial_device) 1113 return 0; 1114 1115 /* If a serial device is already opened, close it first. */ 1116 if (serial_fd >= 0) 1117 close (serial_fd); 1118 1119 /* Open the device file. */ 1120 serial_fd = open (serial_device, 1121 O_RDWR | O_NOCTTY 1122 #if defined(O_SYNC) 1123 /* O_SYNC is used in Linux (and some others?). */ 1124 | O_SYNC 1125 #elif defined(O_FSYNC) 1126 /* O_FSYNC is used in FreeBSD. */ 1127 | O_FSYNC 1128 #endif 1129 ); 1130 if (serial_fd < 0) 1131 return 0; 1132 1133 /* Get the termios parameters. */ 1134 if (tcgetattr (serial_fd, &termios)) 1135 goto fail; 1136 1137 /* Raw mode. */ 1138 #if defined(__sun) 1139 termios.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); 1140 termios.c_oflag &= ~OPOST; 1141 termios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); 1142 termios.c_cflag &= ~(CSIZE|PARENB); 1143 termios.c_cflag |= CS8; 1144 #else 1145 cfmakeraw (&termios); 1146 #endif 1147 1148 /* Set the speed. */ 1149 termios_speed = get_termios_speed (speed); 1150 if (termios_speed == B0) 1151 goto fail; 1152 1153 cfsetispeed (&termios, termios_speed); 1154 cfsetospeed (&termios, termios_speed); 1155 1156 /* Set the word length. */ 1157 termios.c_cflag &= ~CSIZE; 1158 switch (word_len) 1159 { 1160 case UART_5BITS_WORD: 1161 termios.c_cflag |= CS5; 1162 break; 1163 case UART_6BITS_WORD: 1164 termios.c_cflag |= CS6; 1165 break; 1166 case UART_7BITS_WORD: 1167 termios.c_cflag |= CS7; 1168 break; 1169 case UART_8BITS_WORD: 1170 termios.c_cflag |= CS8; 1171 break; 1172 default: 1173 goto fail; 1174 } 1175 1176 /* Set the parity. */ 1177 switch (parity) 1178 { 1179 case UART_NO_PARITY: 1180 termios.c_cflag &= ~PARENB; 1181 break; 1182 case UART_ODD_PARITY: 1183 termios.c_cflag |= PARENB; 1184 termios.c_cflag |= PARODD; 1185 break; 1186 case UART_EVEN_PARITY: 1187 termios.c_cflag |= PARENB; 1188 termios.c_cflag &= ~PARODD; 1189 break; 1190 default: 1191 goto fail; 1192 } 1193 1194 /* Set the length of stop bit. */ 1195 switch (stop_bit_len) 1196 { 1197 case UART_1_STOP_BIT: 1198 termios.c_cflag &= ~CSTOPB; 1199 break; 1200 case UART_2_STOP_BITS: 1201 termios.c_cflag |= CSTOPB; 1202 break; 1203 default: 1204 goto fail; 1205 } 1206 1207 /* Set the parameters. */ 1208 if (tcsetattr (serial_fd, TCSANOW, &termios)) 1209 goto fail; 1210 1211 #ifdef SIMULATE_SLOWNESS_OF_SERIAL 1212 serial_speed = speed; 1213 #endif /* SIMUATE_SLOWNESS_OF_SERIAL */ 1214 1215 /* Get rid of the flag TERM_NEED_INIT from the serial terminal. */ 1216 for (i = 0; term_table[i].name; i++) 1217 { 1218 if (strcmp (term_table[i].name, "serial") == 0) 1219 { 1220 term_table[i].flags &= ~(TERM_NEED_INIT); 1221 break; 1222 } 1223 } 1224 1225 return 1; 1226 1227 fail: 1228 close (serial_fd); 1229 serial_fd = -1; 1230 return 0; 1231 } 1232 1233 /* Set the file name of a serial device (or a pty device). This is a 1234 function specific to the grub shell. */ 1235 void 1236 serial_set_device (const char *device) 1237 { 1238 if (serial_device) 1239 free (serial_device); 1240 1241 serial_device = strdup (device); 1242 } 1243 1244 /* There is no difference between console and hercules in the grub shell. */ 1245 void 1246 hercules_putchar (int c) 1247 { 1248 console_putchar (c); 1249 } 1250 1251 int 1252 hercules_getxy (void) 1253 { 1254 return console_getxy (); 1255 } 1256 1257 void 1258 hercules_gotoxy (int x, int y) 1259 { 1260 console_gotoxy (x, y); 1261 } 1262 1263 void 1264 hercules_cls (void) 1265 { 1266 console_cls (); 1267 } 1268 1269 void 1270 hercules_setcolorstate (color_state state) 1271 { 1272 console_setcolorstate (state); 1273 } 1274 1275 void 1276 hercules_setcolor (int normal_color, int highlight_color) 1277 { 1278 console_setcolor (normal_color, highlight_color); 1279 } 1280 1281 int 1282 hercules_setcursor (int on) 1283 { 1284 return 1; 1285 } 1286 1287 uint32_t amd64_cpuid_supported(void) 1288 { 1289 /* Nothing to do in the simulator. */ 1290 return (1); 1291 } 1292 1293 void amd64_cpuid_insn(uint32_t i, void * r) 1294 { 1295 /* Nothing to do in the simulator. */ 1296 } 1297 1298 void amd64_rdmsr(uint32_t i, uint64_t * p) 1299 { 1300 /* Nothing to do in the simulator. */ 1301 } 1302 1303 void amd64_wrmsr(uint32_t i, const uint64_t * p) 1304 { 1305 /* Nothing to do in the simulator. */ 1306 } 1307 1308 int get_target_operating_mode(void) 1309 { 1310 /* Nothing to do in the simulator. */ 1311 return (1); 1312 } 1313