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