~smartboyhw/wubi/bug-1080090-new

« back to all changes in this revision

Viewing changes to src/grub4dos/grub/.svn/text-base/asmstub.c.svn-base

  • Committer: Howard Chan
  • Date: 2012-11-20 10:16:05 UTC
  • Revision ID: smartboyhw@gmail.com-20121120101605-qfmjfsdynpzg9an9
Added images

Show diffs side-by-side

added added

removed removed

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