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