~smartboyhw/wubi/bug-1080090-new

« back to all changes in this revision

Viewing changes to src/grub4dos/stage2/.svn/text-base/common.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
 
/* common.c - miscellaneous shared variables and routines */
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
 
#include <shared.h>
22
 
#include <iso9660.h>
23
 
#include "pxe.h"
24
 
 
25
 
#ifdef SUPPORT_DISKLESS
26
 
# define GRUB   1
27
 
# include <etherboot.h>
28
 
#endif
29
 
 
30
 
/*
31
 
 *  Shared BIOS/boot data.
32
 
 */
33
 
 
34
 
struct multiboot_info mbi;
35
 
unsigned long saved_drive;
36
 
unsigned long saved_partition;
37
 
char saved_dir[256];
38
 
//unsigned long cdrom_drives[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
39
 
unsigned long cdrom_drive = GRUB_INVALID_DRIVE;
40
 
unsigned long force_cdrom_as_boot_device = 1;
41
 
unsigned long ram_drive;
42
 
unsigned long rd_base = 0;      /* Note the rd_base value of -1 invalidates the ram drive. */
43
 
unsigned long rd_size = 0;      /* The rd_size 0 stands for 4GB, not for length of 0. */
44
 
unsigned long saved_mem_upper;
45
 
unsigned long saved_mem_lower;
46
 
unsigned long saved_mmap_addr;
47
 
unsigned long saved_mmap_length;
48
 
 
49
 
#ifndef STAGE1_5
50
 
/* This saves the maximum size of extended memory (in KB).  */
51
 
unsigned long extended_memory;
52
 
unsigned long init_free_mem_start;
53
 
#endif
54
 
int is64bit = 0;
55
 
int errorcheck = 1;
56
 
 
57
 
/*
58
 
 *  Error code stuff.
59
 
 */
60
 
 
61
 
grub_error_t errnum = ERR_NONE;
62
 
 
63
 
#ifndef STAGE1_5
64
 
 
65
 
char *err_list[] =
66
 
{
67
 
  [ERR_NONE] = 0,
68
 
  [ERR_BAD_ARGUMENT] = "Invalid argument",
69
 
  [ERR_BAD_FILENAME] = "Filename must be either an absolute pathname or blocklist",
70
 
  [ERR_BAD_FILETYPE] = "Bad file or directory type",
71
 
  [ERR_BAD_GZIP_DATA] = "Bad or corrupt data while decompressing file",
72
 
  [ERR_BAD_GZIP_HEADER] = "Bad or incompatible header in compressed file",
73
 
  [ERR_BAD_PART_TABLE] = "Partition table invalid or corrupt",
74
 
  [ERR_BAD_VERSION] = "Mismatched or corrupt version of stage1/stage2",
75
 
  [ERR_BELOW_1MB] = "Loading below 1MB is not supported",
76
 
  [ERR_BOOT_COMMAND] = "Kernel must be loaded before booting",
77
 
  [ERR_BOOT_FAILURE] = "Unknown boot failure",
78
 
  [ERR_BOOT_FEATURES] = "Unsupported Multiboot features requested",
79
 
  [ERR_DEV_FORMAT] = "Unrecognized device string, or you omitted the required DEVICE part which should lead the filename.",
80
 
  [ERR_DEV_NEED_INIT] = "Device not initialized yet",
81
 
  [ERR_DEV_VALUES] = "Invalid device requested",
82
 
  [ERR_EXEC_FORMAT] = "Invalid or unsupported executable format",
83
 
  [ERR_FILELENGTH] = "Filesystem compatibility error, cannot read whole file",
84
 
  [ERR_FILENAME_FORMAT] = "The leading DEVICE of the filename to find must be stripped off,\n\tand DIR for set-root must begin in a slash(/).",
85
 
  [ERR_FILE_NOT_FOUND] = "File not found",
86
 
  [ERR_FSYS_CORRUPT] = "Inconsistent filesystem structure",
87
 
  [ERR_FSYS_MOUNT] = "Cannot mount selected partition",
88
 
  [ERR_GEOM] = "Selected cylinder exceeds maximum supported by BIOS",
89
 
  [ERR_HD_VOL_START_0] = "The BPB hidden_sectors should not be zero for a hard-disk partition boot sector",
90
 
  [ERR_IN_SITU_FLOPPY] = "Only hard drives could be mapped in situ.",
91
 
  [ERR_IN_SITU_MEM] = "Should not use --mem together with --in-situ.",
92
 
  [ERR_NEED_LX_KERNEL] = "Linux kernel must be loaded before initrd",
93
 
  [ERR_NEED_MB_KERNEL] = "Multiboot kernel must be loaded before modules",
94
 
  [ERR_NO_DISK] = "Selected disk does not exist",
95
 
  [ERR_NO_DISK_SPACE] = "No spare sectors on the disk",
96
 
  [ERR_NO_PART] = "No such partition",
97
 
  [ERR_NO_HEADS] = "The number of heads must be specified. The `--heads=0' option tells map to choose a value(but maybe unsuitable) for you",
98
 
  [ERR_NO_SECTORS] = "The number of sectors per track must be specified. The `--sectors-per-track=0' option tells map to choose a value(but maybe unsuitable) for you",
99
 
  [ERR_NON_CONTIGUOUS] = "File for drive emulation must be in one contiguous disk area",
100
 
  [ERR_NUMBER_OVERFLOW] = "Overflow while parsing number",
101
 
  [ERR_NUMBER_PARSING] = "Error while parsing number",
102
 
  [ERR_OUTSIDE_PART] = "Attempt to access block outside partition",
103
 
  [ERR_PRIVILEGED] = "Must be authenticated",
104
 
  [ERR_READ] = "Disk read error",
105
 
  [ERR_SYMLINK_LOOP] = "Too many symbolic links",
106
 
  [ERR_UNALIGNED] = "File is not sector aligned",
107
 
  [ERR_UNRECOGNIZED] = "Unrecognized command",
108
 
  [ERR_WONT_FIT] = "Selected item cannot fit into memory",
109
 
  [ERR_WRITE] = "Disk write error",
110
 
  [ERR_INT13_ON_HOOK] = "The int13 handler already on hook",
111
 
  [ERR_INT13_OFF_HOOK] = "The int13 handler not yet on hook",
112
 
  [ERR_NO_DRIVE_MAPPED] = "Refuse to hook int13 because of empty drive map table",
113
 
  [ERR_INVALID_HEADS] = "Invalid heads. Should be between 0 and 256(0 means auto)",
114
 
  [ERR_INVALID_SECTORS] = "Invalid sectors. Should be between 0 and 63(0 means auto)",
115
 
  [ERR_SPECIFY_GEOM] = "Should not specify geometry when mapping a whole drive or when emulating a hard disk with a logical partition",
116
 
  [ERR_EXTENDED_PARTITION] = "Extended partition table is invalid, or its CHS values conflict with the BPB in a logical partition",
117
 
  [ERR_DEL_MEM_DRIVE] = "You should delete other mem drive first, or use `--mem' option to force the deletion",
118
 
  [ERR_SPECIFY_MEM] = "Should not specify `--mem' when mapping a whole drive",
119
 
  [ERR_SPECIFY_RESTRICTION] = "Options --read-only, --fake-write and --unsafe-boot are mutually exclusive. Should not specify them repeatedly.",
120
 
  [ERR_INVALID_FLOPPIES] = "Invalid floppies. Should be between 0 and 2",
121
 
  [ERR_INVALID_HARDDRIVES] = "Invalid harddrives. Should be between 0 and 127",
122
 
  [ERR_INVALID_LOAD_SEGMENT] = "Invalid load segment. Should be between 0 and 0x9FFF",
123
 
  [ERR_INVALID_LOAD_OFFSET] = "Invalid load offset. Should be between 0 and 0xFFFF",
124
 
  [ERR_INVALID_LOAD_LENGTH] = "Invalid load length. Should be between 512 and 0xA0000",
125
 
  [ERR_INVALID_SKIP_LENGTH] = "Invalid skip length. Should be non-negative and less than the file size",
126
 
  [ERR_INVALID_BOOT_CS] = "Invalid boot CS. Should be between 0 and 0xFFFF",
127
 
  [ERR_INVALID_BOOT_IP] = "Invalid boot IP. Should be between 0 and 0xFFFF",
128
 
  [ERR_INVALID_RAM_DRIVE] = "Invalid ram_drive. Should be between 0 and 254",
129
 
//  [ERR_INVALID_RD_BASE] = "Invalid rd_base. Should not be 0xffffffff",
130
 
//  [ERR_INVALID_RD_SIZE] = "Invalid rd_size. Should not be 0",
131
 
  [ERR_MD_BASE] = "When mapping whole mem device at a fixed location, you must specify --mem to a value > 0.",
132
 
  [ERR_RD_BASE] = "RD_BASE must be sector-aligned and non-zero for mapping at a fixed location",
133
 
  [ERR_DOS_BACKUP] = "GRUB was not booted from DOS, or the backup copy of DOS at physical\naddress 0x200000 is corrupt",
134
 
  [ERR_ENABLE_A20] = "Failed to turn on Gate A20!",
135
 
  [ERR_DISABLE_A20] = "Failed to turn off Gate A20!",
136
 
  [ERR_DEFAULT_FILE] = "Invalid DEFAULT file format. Please copy a valid DEFAULT file from the grub4dos release and try again. Also note that the DEFAULT file must be uncompressed.",
137
 
  [ERR_PARTITION_TABLE_FULL] = "Cannot use --in-situ because the partition table is full(i.e., all the 4 entries are in use).",
138
 
  [ERR_MD5_FORMAT] = "Unrecognized md5 string. You must create it using the MD5CRYPT command.",
139
 
 
140
 
};
141
 
 
142
 
 
143
 
/* static for BIOS memory map fakery */
144
 
static struct AddrRangeDesc fakemap[3] =
145
 
{
146
 
  {20, 0, 0, MB_ARD_MEMORY},
147
 
  {20, 0x100000, 0, MB_ARD_MEMORY},
148
 
  {20, 0x1000000, 0, MB_ARD_MEMORY}
149
 
};
150
 
 
151
 
/* A big problem is that the memory areas aren't guaranteed to be:
152
 
   (1) contiguous, (2) sorted in ascending order, or (3) non-overlapping.
153
 
   Thus this kludge.  */
154
 
static unsigned long
155
 
mmap_avail_at (unsigned long bottom)
156
 
{
157
 
  unsigned long long top;
158
 
  unsigned long addr;
159
 
  int cont;
160
 
  
161
 
  top = bottom;
162
 
  do
163
 
    {
164
 
      for (cont = 0, addr = saved_mmap_addr;
165
 
           addr < saved_mmap_addr + saved_mmap_length;
166
 
           addr += *((unsigned long *) addr) + 4)
167
 
        {
168
 
          struct AddrRangeDesc *desc = (struct AddrRangeDesc *) addr;
169
 
          
170
 
          if (desc->Type == MB_ARD_MEMORY
171
 
              && desc->BaseAddr <= top
172
 
              && desc->BaseAddr + desc->Length > top)
173
 
            {
174
 
              top = desc->BaseAddr + desc->Length;
175
 
              cont++;
176
 
            }
177
 
        }
178
 
    }
179
 
  while (cont);
180
 
 
181
 
  /* For now, GRUB assumes 32bits addresses, so...  */
182
 
  if (top > 0xFFFFFFFF)
183
 
    top = 0xFFFFFFFF;
184
 
  
185
 
  return (unsigned long) top - bottom;
186
 
}
187
 
#endif /* ! STAGE1_5 */
188
 
 
189
 
/* This queries for BIOS information.  */
190
 
void
191
 
init_bios_info (void)
192
 
{
193
 
#ifndef STAGE1_5
194
 
  unsigned long cont, memtmp, addr;
195
 
  int drive;
196
 
#endif
197
 
#ifndef GRUB_UTIL
198
 
#ifndef STAGE1_5
199
 
  unsigned long force_pxe_as_boot_device;
200
 
#endif /* ! STAGE1_5 */
201
 
#endif /* ! GRUB_UTIL */
202
 
 
203
 
  /*
204
 
   *  Get information from BIOS on installed RAM.
205
 
   */
206
 
 
207
 
#ifndef STAGE1_5
208
 
  DEBUG_SLEEP
209
 
  printf("\rGet lower memory... ");
210
 
#endif
211
 
  saved_mem_lower = get_memsize (0);    /* int12 --------safe enough */
212
 
#ifndef STAGE1_5
213
 
  printf("\rGet upper memory... ");
214
 
#endif
215
 
  saved_mem_upper = get_memsize (1);    /* int15/88 -----safe enough */
216
 
 
217
 
#ifndef STAGE1_5
218
 
  /*
219
 
   *  We need to call this somewhere before trying to put data
220
 
   *  above 1 MB, since without calling it, address line 20 will be wired
221
 
   *  to 0.  Not too desirable.
222
 
   */
223
 
 
224
 
#ifndef GRUB_UTIL
225
 
  debug = debug_boot + 1;
226
 
  DEBUG_SLEEP
227
 
  printf("\rTurning on gate A20...                          ");
228
 
#if 1
229
 
    {
230
 
        unsigned long j;
231
 
        int wait;
232
 
        int time1;
233
 
        int time2;
234
 
 
235
 
        if (gateA20 (1))                        /* int15/24 -----safe enough */
236
 
        {
237
 
                /* wipe out the messages on success */
238
 
                printf("\r                                                                \r");
239
 
                wait = 0;       /* sleep 0 second after A20 control */
240
 
        } else {
241
 
                printf("Failure! Report bug, please!\n");
242
 
                wait = 5;       /* sleep 5 second on failure */
243
 
        }
244
 
 
245
 
        /* Get current time.  */
246
 
        while ((time2 = getrtsecs ()) == 0xFF);
247
 
 
248
 
        for (j = 0; j < 0x00800000; j++)
249
 
        {
250
 
          if ((time1 = getrtsecs ()) != time2 && time1 != 0xFF)
251
 
            {
252
 
              if (wait == 0)
253
 
                  break;
254
 
              
255
 
              time2 = time1;
256
 
              wait--;
257
 
            }
258
 
        }
259
 
    }
260
 
#else
261
 
  extern void grub2_gate_a20 (int on);
262
 
  grub2_gate_a20 (1);
263
 
  printf("\r                        \r");       /* wipe out the messages */
264
 
#endif
265
 
  DEBUG_SLEEP
266
 
#endif
267
 
 
268
 
  /* Store the size of extended memory in EXTENDED_MEMORY, in order to
269
 
     tell it to non-Multiboot OSes.  */
270
 
  extended_memory = saved_mem_upper;
271
 
  
272
 
  /*
273
 
   *  The MBI.MEM_UPPER variable only recognizes upper memory in the
274
 
   *  first memory region.  If there are multiple memory regions,
275
 
   *  the rest are reported to a Multiboot-compliant OS, but otherwise
276
 
   *  unused by GRUB.
277
 
   */
278
 
 
279
 
  addr = get_code_end ();
280
 
  saved_mmap_addr = addr;
281
 
  saved_mmap_length = 0;
282
 
  cont = 0;
283
 
 
284
 
  printf("\rGet E820 memory...           ");
285
 
  do
286
 
    {
287
 
      cont = get_mmap_entry ((void *) addr, cont);      /* int15/e820 ------ will write memory! */
288
 
 
289
 
      /* If the returned buffer's length is zero, quit. */
290
 
      if (! *((unsigned long *) addr))
291
 
        break;
292
 
 
293
 
      saved_mmap_length += *((unsigned long *) addr) + 4;
294
 
      addr += *((unsigned long *) addr) + 4;
295
 
    }
296
 
  while (cont);
297
 
 
298
 
  if (! (saved_mmap_length))
299
 
        printf("\rGet E801 memory...           ");
300
 
 
301
 
  if (saved_mmap_length)
302
 
    {
303
 
      unsigned long long max_addr;
304
 
      
305
 
      /*
306
 
       *  This is to get the lower memory, and upper memory (up to the
307
 
       *  first memory hole), into the MBI.MEM_{LOWER,UPPER}
308
 
       *  elements.  This is for OS's that don't care about the memory
309
 
       *  map, but might care about total RAM available.
310
 
       */
311
 
      saved_mem_lower = mmap_avail_at (0) >> 10;
312
 
      saved_mem_upper = mmap_avail_at (0x100000) >> 10;
313
 
 
314
 
      /* Find the maximum available address. Ignore any memory holes.  */
315
 
      for (max_addr = 0, addr = saved_mmap_addr;
316
 
           addr < saved_mmap_addr + saved_mmap_length;
317
 
           addr += *((unsigned long *) addr) + 4)
318
 
        {
319
 
          struct AddrRangeDesc *desc = (struct AddrRangeDesc *) addr;
320
 
          
321
 
          if (desc->Type == MB_ARD_MEMORY && desc->Length > 0
322
 
              && desc->BaseAddr + desc->Length > max_addr)
323
 
            max_addr = desc->BaseAddr + desc->Length;
324
 
        }
325
 
 
326
 
      extended_memory = (max_addr - 0x100000) >> 10;
327
 
    }
328
 
  else if ((memtmp = get_eisamemsize ()) != -1)         /* int15/e801 ------safe enough */
329
 
    {
330
 
      cont = memtmp & ~0xFFFF;
331
 
      memtmp = memtmp & 0xFFFF;
332
 
 
333
 
      if (cont != 0)
334
 
        extended_memory = (cont >> 10) + 0x3c00;
335
 
      else
336
 
        extended_memory = memtmp;
337
 
      
338
 
      if (!cont || (memtmp == 0x3c00))
339
 
        memtmp += (cont >> 10);
340
 
      else
341
 
        {
342
 
          /* XXX should I do this at all ??? */
343
 
 
344
 
          saved_mmap_addr = (unsigned long) fakemap;
345
 
          saved_mmap_length = sizeof (fakemap);
346
 
          fakemap[0].Length = (saved_mem_lower << 10);
347
 
          fakemap[1].Length = (memtmp << 10);
348
 
          fakemap[2].Length = cont;
349
 
        }
350
 
 
351
 
      saved_mem_upper = memtmp;
352
 
    }
353
 
 
354
 
  printf("\r                        \r");       /* wipe out the messages */
355
 
 
356
 
  mbi.mem_upper = saved_mem_upper;
357
 
  mbi.mem_lower = saved_mem_lower;
358
 
  mbi.mmap_addr = saved_mmap_addr;
359
 
  mbi.mmap_length = saved_mmap_length;
360
 
 
361
 
#ifndef GRUB_UTIL
362
 
  is64bit = check_64bit ();
363
 
#endif
364
 
 
365
 
  /* Get the drive info.  */
366
 
  /* FIXME: This should be postponed until a Multiboot kernel actually
367
 
     requires it, because this could slow down the start-up
368
 
     unreasonably.  */
369
 
  mbi.drives_length = 0;
370
 
  mbi.drives_addr = addr;
371
 
 
372
 
  /* For now, GRUB doesn't probe floppies, since it is trivial to map
373
 
     floppy drives to BIOS drives.  */
374
 
#ifdef GRUB_UTIL
375
 
#define FIND_DRIVES 8
376
 
#else
377
 
#define FIND_DRIVES (*((char *)0x475))
378
 
#endif
379
 
  if (debug > 1)
380
 
        grub_printf ("hard drives: %d, int13: %X, int15: %X\n", FIND_DRIVES, *(unsigned long *)0x4C, *(unsigned long *)0x54);
381
 
  DEBUG_SLEEP
382
 
 
383
 
  for (drive = 0x80; drive < 0x80 + FIND_DRIVES; drive++)
384
 
    {
385
 
      struct drive_info *info = (struct drive_info *) addr;
386
 
//      unsigned short *port;
387
 
      
388
 
      /* Get the geometry. This ensures that the drive is present.  */
389
 
 
390
 
      if (debug > 1)
391
 
        grub_printf ("get_diskinfo(%X), ", drive);
392
 
 
393
 
      if (get_diskinfo (drive, &tmp_geom))
394
 
        continue;//break;
395
 
 
396
 
      if (debug > 1)
397
 
        grub_printf (" %sC/H/S=%d/%d/%d, Sector Count/Size=%d/%d\n",
398
 
                (tmp_geom.flags & BIOSDISK_FLAG_LBA_EXTENSION) ? "LBA, " : "",
399
 
                tmp_geom.cylinders, tmp_geom.heads, tmp_geom.sectors,
400
 
                tmp_geom.total_sectors, tmp_geom.sector_size);
401
 
      
402
 
      /* Set the information.  */
403
 
      info->drive_number = drive;
404
 
      info->drive_mode = ((tmp_geom.flags & BIOSDISK_FLAG_LBA_EXTENSION)
405
 
                          ? MB_DI_LBA_MODE : MB_DI_CHS_MODE);
406
 
      info->drive_cylinders = tmp_geom.cylinders;
407
 
      info->drive_heads = tmp_geom.heads;
408
 
      info->drive_sectors = tmp_geom.sectors;
409
 
 
410
 
      addr += sizeof (struct drive_info);
411
 
 
412
 
      info->size = addr - (unsigned long) info;
413
 
      mbi.drives_length += info->size;
414
 
    }
415
 
 
416
 
  init_free_mem_start = addr;
417
 
 
418
 
  DEBUG_SLEEP
419
 
 
420
 
  /*
421
 
   *  Initialize other Multiboot Info flags.
422
 
   */
423
 
 
424
 
  mbi.flags = (MB_INFO_MEMORY | MB_INFO_CMDLINE | MB_INFO_BOOTDEV | MB_INFO_DRIVE_INFO | MB_INFO_CONFIG_TABLE | MB_INFO_BOOT_LOADER_NAME);
425
 
  if (saved_mmap_length)
426
 
    mbi.flags |= MB_INFO_MEM_MAP;
427
 
  
428
 
#endif /* STAGE1_5 */
429
 
 
430
 
#ifndef GRUB_UTIL
431
 
#ifndef STAGE1_5
432
 
    force_pxe_as_boot_device = 0;
433
 
    if (! ((*(char *)0x8205) & 0x01))   /* if it is not disable pxe */
434
 
    {
435
 
        //pxe_detect();
436
 
        if (! pxe_entry)
437
 
        {
438
 
            PXENV_GET_CACHED_INFO_t get_cached_info;
439
 
 
440
 
            printf("\rbegin pxe scan...            ");
441
 
            pxe_scan ();
442
 
            DEBUG_SLEEP
443
 
 
444
 
            if (pxe_entry)
445
 
            {
446
 
                pxe_basemem = *((unsigned short*)0x413);
447
 
 
448
 
                get_cached_info.PacketType = PXENV_PACKET_TYPE_DHCP_ACK;
449
 
                get_cached_info.Buffer = get_cached_info.BufferSize = 0;
450
 
 
451
 
                printf("\rbegin pxe call(type=DHCP_ACK)...            ");
452
 
                pxe_call (PXENV_GET_CACHED_INFO, &get_cached_info);
453
 
                DEBUG_SLEEP
454
 
 
455
 
                if (get_cached_info.Status)
456
 
                {
457
 
                        grub_printf ("\nFatal: DHCP_ACK failure!\n");
458
 
                        goto pxe_init_fail;
459
 
                }
460
 
 
461
 
                discover_reply = LINEAR(get_cached_info.Buffer);
462
 
 
463
 
                pxe_yip = discover_reply->yip;
464
 
                pxe_sip = discover_reply->sip;
465
 
                pxe_gip = discover_reply->gip;
466
 
 
467
 
                pxe_mac_type = discover_reply->Hardware;
468
 
                pxe_mac_len = discover_reply->Hardlen;
469
 
                grub_memmove (&pxe_mac, &discover_reply->CAddr, pxe_mac_len);
470
 
 
471
 
                get_cached_info.PacketType = PXENV_PACKET_TYPE_CACHED_REPLY;
472
 
                get_cached_info.Buffer = get_cached_info.BufferSize = 0;
473
 
 
474
 
                printf("\rbegin pxe call(type=CACHED_REPLY)...            ");
475
 
                pxe_call (PXENV_GET_CACHED_INFO, &get_cached_info);
476
 
                DEBUG_SLEEP
477
 
 
478
 
                if (get_cached_info.Status)
479
 
                {
480
 
                        grub_printf ("\nFatal: CACHED_REPLY failure!\n");
481
 
pxe_init_fail:
482
 
                        pxe_keep = 0;
483
 
                        pxe_unload ();
484
 
                        DEBUG_SLEEP
485
 
                        pxe_entry = 0;
486
 
                        discover_reply = 0;
487
 
                        goto pxe_init_done;
488
 
                }
489
 
 
490
 
                discover_reply = LINEAR(get_cached_info.Buffer);
491
 
 
492
 
                /* on pxe boot, we only use preset_menu */
493
 
                if (preset_menu != (char*)0x800)
494
 
                        preset_menu = (char*)0x800;
495
 
                if (*config_file)
496
 
                        *config_file = 0;
497
 
                force_pxe_as_boot_device = 1;
498
 
                if (bios_id != 1)               /* if it is not Bochs ... */
499
 
                        goto set_root;;         /* ... skip cdrom check. */
500
 
            }
501
 
        }
502
 
    }
503
 
pxe_init_done:
504
 
#endif /* STAGE1_5 */
505
 
#endif /* ! GRUB_UTIL */
506
 
 
507
 
#if !defined(STAGE1_5) && !defined(GRUB_UTIL)
508
 
  /* Set cdrom drive.  */
509
 
    
510
 
    /* Get the geometry.  */
511
 
    if (debug > 1)
512
 
        printf("\rboot drive=%X, ", boot_drive);
513
 
    cdrom_drive = get_cdinfo (boot_drive, &tmp_geom);
514
 
    if (! cdrom_drive || cdrom_drive != boot_drive)
515
 
        cdrom_drive = GRUB_INVALID_DRIVE;
516
 
    if (cdrom_drive == GRUB_INVALID_DRIVE)
517
 
    {
518
 
        /* read the first sector of the drive */
519
 
        if (((unsigned char)boot_drive) >= 0x80 + FIND_DRIVES)
520
 
        {
521
 
                struct disk_address_packet
522
 
                {
523
 
                        unsigned char length;
524
 
                        unsigned char reserved;
525
 
                        unsigned short blocks;
526
 
                        unsigned long buffer;
527
 
                        unsigned long long block;
528
 
 
529
 
                        unsigned char dummy[16];
530
 
                } __attribute__ ((packed)) *dap;
531
 
 
532
 
                dap = (struct disk_address_packet *)0x580;
533
 
 
534
 
                dap->length = 0x10;
535
 
                dap->reserved = 0;
536
 
                dap->blocks = 1;
537
 
                dap->buffer = 0x5F80/*SCRATCHSEG*/ << 16;
538
 
                dap->block = 0;
539
 
 
540
 
                /* set a known value */
541
 
                grub_memset ((char *)0x5F800, 0xEC, 0x800);
542
 
                biosdisk_int13_extensions (0x4200, (unsigned char)boot_drive, dap);
543
 
                /* see if it is a big sector */
544
 
                {
545
 
                        char *p;
546
 
                        for (p = (char *)0x5FA00; p < (char *)0x60000; p++)
547
 
                        {
548
 
                                if ((*p) != (char)0xEC)
549
 
                                {
550
 
                                        cdrom_drive = boot_drive;
551
 
                                        break;
552
 
                                }
553
 
                        }
554
 
                }
555
 
 
556
 
        } /* if (geometry->flags & BIOSDISK_FLAG_LBA_EXTENSION) */
557
 
    }
558
 
 
559
 
    if (debug > 1)
560
 
        printf("%s\n", cdrom_drive == GRUB_INVALID_DRIVE ? "Not CD":"Is CD");
561
 
  DEBUG_SLEEP
562
 
#endif
563
 
  
564
 
#if !defined(STAGE1_5) && !defined(GRUB_UTIL)
565
 
 
566
 
  if (cdrom_drive == GRUB_INVALID_DRIVE)  
567
 
  {
568
 
    int err;
569
 
    int version;
570
 
    struct drive_parameters *drp = (struct drive_parameters *)0x600;
571
 
 
572
 
#undef FIND_DRIVES
573
 
#ifdef GRUB_UTIL
574
 
#define FIND_DRIVES 8
575
 
#else
576
 
#define FIND_DRIVES (*((char *)0x475))
577
 
#endif
578
 
    for (drive = 0xFF; drive >= 0x7F; drive--)
579
 
    {
580
 
      if (drive >= 0x80 && drive < 0x80 + FIND_DRIVES)
581
 
        continue;
582
 
      
583
 
      /* Get the geometry.  */
584
 
      if (debug > 1)
585
 
        grub_printf ("\rget_cdinfo(%X),", drive);
586
 
      cdrom_drive = get_cdinfo (drive, &tmp_geom);
587
 
      if (cdrom_drive)
588
 
      {
589
 
        if (drive != 0x7F)
590
 
          break;
591
 
        drive = cdrom_drive;
592
 
        cdrom_drive = get_cdinfo (drive, &tmp_geom);
593
 
        if (cdrom_drive == drive)
594
 
          break;
595
 
        drive = 0x7F;
596
 
      }
597
 
    
598
 
      cdrom_drive = GRUB_INVALID_DRIVE;
599
 
    
600
 
      /* Some buggy BIOSes will hang at EBIOS `Get Drive Parameters' call
601
 
       * (INT 13h function 48h). So we only do further checks for Bochs.
602
 
       */
603
 
      
604
 
      if (bios_id != 1)         /* if it is not Bochs ... */
605
 
        continue;               /* ... skip and try next drive. */
606
 
      
607
 
      /* When qemu has a cdrom attached but not booted from cdrom, its
608
 
       * `get bootable cdrom status call', the int13/ax=4B01, returns CF=0
609
 
       * but with a wrong `Bootable CD-ROM Specification Packet' as follows:
610
 
       *
611
 
       * The first byte(packet size) is 0x13, all the rest bytes are 0's.
612
 
       * 
613
 
       * So we need to call get_diskinfo() here as a workaround.
614
 
       *
615
 
       *                (The bug was reported by Jacopo Lazzari. Thanks!)
616
 
       */
617
 
 
618
 
      if (drive >= 0x80)
619
 
      {
620
 
        version = check_int13_extensions (drive);
621
 
 
622
 
        if (! (version & 1)) /* not support functions 42h-44h, 47h-48h */
623
 
            continue;   /* failure, try next drive. */
624
 
        
625
 
        /* It is safe to clear out DRP.  */
626
 
        grub_memset (drp, 0, sizeof (struct drive_parameters));
627
 
          
628
 
        drp->size = sizeof (struct drive_parameters) - 16;
629
 
          
630
 
        err = biosdisk_int13_extensions (0x4800, drive, drp);
631
 
        if (! err && drp->bytes_per_sector == ISO_SECTOR_SIZE)
632
 
        {
633
 
            /* Assume it is CDROM.  */
634
 
            cdrom_drive = drive;
635
 
            break;
636
 
        }
637
 
      } /* if (drive >= 0x80) */
638
 
    
639
 
    } /* for (drive = 0x7F; drive < 0xff; drive++) */
640
 
  } /* if (cdrom_drive == GRUB_INVALID_DRIVE) */
641
 
#undef FIND_DRIVES
642
 
  
643
 
//  if (cdrom_drive != GRUB_INVALID_DRIVE)  
644
 
//  {
645
 
//      /* skip pxe init if booting from cdrom */
646
 
//      *(char *)0x8205 |= 0x01;
647
 
//  }
648
 
 
649
 
  if (debug > 1)
650
 
    grub_printf(" cdrom_drive == %X.\n", cdrom_drive);
651
 
  DEBUG_SLEEP
652
 
#endif /* ! STAGE1_5 && ! GRUB_UTIL */
653
 
 
654
 
  /* check if the no-emulation-mode bootable cdrom exists. */
655
 
  
656
 
  /* if cdrom_drive is active, we assume it is the boot device */
657
 
  if (saved_entryno == 0 && force_cdrom_as_boot_device)
658
 
        force_cdrom_as_boot_device = 0;
659
 
  if (cdrom_drive != GRUB_INVALID_DRIVE && force_cdrom_as_boot_device)
660
 
  {
661
 
    boot_drive = cdrom_drive;   /* force it to be the boot drive */
662
 
  }
663
 
 
664
 
  if (boot_drive == cdrom_drive)
665
 
        /* force it to be "whole drive" without partition table */
666
 
        install_partition = 0xFFFFFF;
667
 
 
668
 
#ifndef GRUB_UTIL
669
 
#ifndef STAGE1_5
670
 
set_root:
671
 
 
672
 
  if (force_pxe_as_boot_device)
673
 
  {
674
 
        boot_drive = PXE_DRIVE;
675
 
        install_partition = 0xFFFFFF;
676
 
  }
677
 
#endif /* ! STAGE1_5 */
678
 
#endif /* ! GRUB_UTIL */
679
 
 
680
 
  /* Set root drive and partition.  */
681
 
  saved_drive = boot_drive;
682
 
  saved_partition = install_partition;
683
 
 
684
 
#ifndef GRUB_UTIL
685
 
#ifndef STAGE1_5
686
 
  debug = 1;
687
 
  if (! atapi_dev_count)
688
 
    min_cdrom_id = (cdrom_drive < 0xE0 && cdrom_drive >= 0xC0) ? 0xE0 : 0xC0;
689
 
  
690
 
  /* if grub.exe is booted as a Linux kernel, check the initrd disk. */
691
 
 
692
 
  /* the real mode zero page(only the beginning 2 sectors, the boot params) is loaded at 0xA00 */
693
 
 
694
 
  /* check the header signature "HdrS" (0x53726448) */
695
 
 
696
 
  ram_drive = 0x7f;     /* the default ram_drive is a floppy. */
697
 
  if (*(unsigned long*)(int*)(0xA00 + 0x202) == 0x53726448)
698
 
  {
699
 
        unsigned long initrd_addr;
700
 
        unsigned long initrd_size;
701
 
        
702
 
        initrd_addr = *(unsigned long*)(int*)(0xA00 + 0x218);
703
 
        initrd_size = *(unsigned long*)(int*)(0xA00 + 0x21c);
704
 
        if (initrd_addr && initrd_size)
705
 
        {
706
 
            rd_base = initrd_addr;
707
 
            rd_size = initrd_size;
708
 
 
709
 
            /* check if there is a partition table */
710
 
            if (*(unsigned short *)(initrd_addr + 0x40) == 0xAA55)
711
 
            {
712
 
                if (! probe_mbr ((struct master_and_dos_boot_sector *)initrd_addr, 0, initrd_size, 0))
713
 
                    ram_drive = 0xfe;   /* partition table is valid, so let it be a harddrive */
714
 
                else
715
 
                    grub_printf ("\nUnrecognized partition table for RAM DRIVE; assuming floppy. Please rebuild\nit using a Microsoft-compatible FDISK tool, if the INITRD is a hard-disk image.\n");
716
 
            }
717
 
        }
718
 
  }
719
 
#endif /* ! STAGE1_5 */
720
 
#endif /* ! GRUB_UTIL */
721
 
 
722
 
  /* Start main routine here.  */
723
 
  
724
 
  grub_printf("Starting cmain() ... ");
725
 
  
726
 
#if !defined(STAGE1_5) && !defined(GRUB_UTIL)
727
 
  DEBUG_SLEEP
728
 
#endif /* ! STAGE1_5 && ! GRUB_UTIL */
729
 
//  cmain ();   /* moved into asm.S and asmstub.c */
730
 
}