Home | History | Annotate | Download | only in stage2
      1 /* disk_io.c - implement abstract BIOS disk input and output */
      2 /*
      3  *  GRUB  --  GRand Unified Bootloader
      4  *  Copyright (C) 1999,2000,2001,2002,2003,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 
     22 #include <shared.h>
     23 #include <filesys.h>
     24 
     25 #ifdef SUPPORT_NETBOOT
     26 # define GRUB	1
     27 # include <etherboot.h>
     28 #endif
     29 
     30 #ifdef GRUB_UTIL
     31 # include <device.h>
     32 #endif
     33 
     34 /* instrumentation variables */
     35 void (*disk_read_hook) (int, int, int) = NULL;
     36 void (*disk_read_func) (int, int, int) = NULL;
     37 
     38 #ifndef STAGE1_5
     39 int print_possibilities;
     40 
     41 static int do_completion;
     42 static int unique;
     43 static char *unique_string;
     44 
     45 #endif
     46 
     47 int fsmax;
     48 struct fsys_entry fsys_table[NUM_FSYS + 1] =
     49 {
     50   /* TFTP should come first because others don't handle net device.  */
     51 # ifdef FSYS_TFTP
     52   {"tftp", tftp_mount, tftp_read, tftp_dir, tftp_close, 0},
     53 # endif
     54 # ifdef FSYS_FAT
     55   {"fat", fat_mount, fat_read, fat_dir, 0, 0},
     56 # endif
     57 # ifdef FSYS_EXT2FS
     58   {"ext2fs", ext2fs_mount, ext2fs_read, ext2fs_dir, 0, 0},
     59 # endif
     60 # ifdef FSYS_MINIX
     61   {"minix", minix_mount, minix_read, minix_dir, 0, 0},
     62 # endif
     63 # ifdef FSYS_REISERFS
     64   {"reiserfs", reiserfs_mount, reiserfs_read, reiserfs_dir, 0, reiserfs_embed},
     65 # endif
     66 # ifdef FSYS_VSTAFS
     67   {"vstafs", vstafs_mount, vstafs_read, vstafs_dir, 0, 0},
     68 # endif
     69 # ifdef FSYS_JFS
     70   {"jfs", jfs_mount, jfs_read, jfs_dir, 0, jfs_embed},
     71 # endif
     72 # ifdef FSYS_XFS
     73   {"xfs", xfs_mount, xfs_read, xfs_dir, 0, 0},
     74 # endif
     75 # ifdef FSYS_UFS2
     76   {"ufs2", ufs2_mount, ufs2_read, ufs2_dir, 0, ufs2_embed},
     77 # endif
     78 # ifdef FSYS_ISO9660
     79   {"iso9660", iso9660_mount, iso9660_read, iso9660_dir, 0, 0},
     80 # endif
     81   /* XX FFS should come last as it's superblock is commonly crossing tracks
     82      on floppies from track 1 to 2, while others only use 1.  */
     83 # ifdef FSYS_FFS
     84   {"ffs", ffs_mount, ffs_read, ffs_dir, 0, ffs_embed},
     85 # endif
     86   {0, 0, 0, 0, 0, 0}
     87 };
     88 
     89 
     90 /* These have the same format as "boot_drive" and "install_partition", but
     91    are meant to be working values. */
     92 unsigned long current_drive = GRUB_INVALID_DRIVE;
     93 unsigned long current_partition;
     94 
     95 #ifndef STAGE1_5
     96 /* The register ESI should contain the address of the partition to be
     97    used for loading a chain-loader when chain-loading the loader.  */
     98 unsigned long boot_part_addr = 0;
     99 #endif
    100 
    101 /*
    102  *  Global variables describing details of the filesystem
    103  */
    104 
    105 /* FIXME: BSD evil hack */
    106 #include "freebsd.h"
    107 int bsd_evil_hack;
    108 
    109 /* filesystem type */
    110 int fsys_type = NUM_FSYS;
    111 #ifndef NO_BLOCK_FILES
    112 static int block_file = 0;
    113 #endif /* NO_BLOCK_FILES */
    114 
    115 /* these are the translated numbers for the open partition */
    116 unsigned long part_start;
    117 unsigned long part_length;
    118 
    119 int current_slice;
    120 
    121 /* disk buffer parameters */
    122 int buf_drive = -1;
    123 int buf_track;
    124 struct geometry buf_geom;
    125 
    126 /* filesystem common variables */
    127 int filepos;
    128 int filemax;
    129 
    130 static inline unsigned long
    131 log2 (unsigned long word)
    132 {
    133   asm volatile ("bsfl %1,%0"
    134 		: "=r" (word)
    135 		: "r" (word));
    136   return word;
    137 }
    138 
    139 int
    140 rawread (int drive, int sector, int byte_offset, int byte_len, char *buf)
    141 {
    142   int slen, sectors_per_vtrack;
    143   int sector_size_bits = log2 (buf_geom.sector_size);
    144 
    145   if (byte_len <= 0)
    146     return 1;
    147 
    148   while (byte_len > 0 && !errnum)
    149     {
    150       int soff, num_sect, track, size = byte_len;
    151       char *bufaddr;
    152 
    153       /*
    154        *  Check track buffer.  If it isn't valid or it is from the
    155        *  wrong disk, then reset the disk geometry.
    156        */
    157       if (buf_drive != drive)
    158 	{
    159 	  if (get_diskinfo (drive, &buf_geom))
    160 	    {
    161 	      errnum = ERR_NO_DISK;
    162 	      return 0;
    163 	    }
    164 	  buf_drive = drive;
    165 	  buf_track = -1;
    166 	  sector_size_bits = log2 (buf_geom.sector_size);
    167 	}
    168 
    169       /* Make sure that SECTOR is valid.  */
    170       if (sector < 0 || sector >= buf_geom.total_sectors)
    171 	{
    172 	  errnum = ERR_GEOM;
    173 	  return 0;
    174 	}
    175 
    176       slen = ((byte_offset + byte_len + buf_geom.sector_size - 1)
    177 	      >> sector_size_bits);
    178 
    179       /* Eliminate a buffer overflow.  */
    180       if ((buf_geom.sectors << sector_size_bits) > BUFFERLEN)
    181 	sectors_per_vtrack = (BUFFERLEN >> sector_size_bits);
    182       else
    183 	sectors_per_vtrack = buf_geom.sectors;
    184 
    185       /* Get the first sector of track.  */
    186       soff = sector % sectors_per_vtrack;
    187       track = sector - soff;
    188       num_sect = sectors_per_vtrack - soff;
    189       bufaddr = ((char *) BUFFERADDR
    190 		 + (soff << sector_size_bits) + byte_offset);
    191 
    192       if (track != buf_track)
    193 	{
    194 	  int bios_err, read_start = track, read_len = sectors_per_vtrack;
    195 
    196 	  /*
    197 	   *  If there's more than one read in this entire loop, then
    198 	   *  only make the earlier reads for the portion needed.  This
    199 	   *  saves filling the buffer with data that won't be used!
    200 	   */
    201 	  if (slen > num_sect)
    202 	    {
    203 	      read_start = sector;
    204 	      read_len = num_sect;
    205 	      bufaddr = (char *) BUFFERADDR + byte_offset;
    206 	    }
    207 
    208 	  bios_err = biosdisk (BIOSDISK_READ, drive, &buf_geom,
    209 			       read_start, read_len, BUFFERSEG);
    210 	  if (bios_err)
    211 	    {
    212 	      buf_track = -1;
    213 
    214 	      if (bios_err == BIOSDISK_ERROR_GEOMETRY)
    215 		errnum = ERR_GEOM;
    216 	      else
    217 		{
    218 		  /*
    219 		   *  If there was an error, try to load only the
    220 		   *  required sector(s) rather than failing completely.
    221 		   */
    222 		  if (slen > num_sect
    223 		      || biosdisk (BIOSDISK_READ, drive, &buf_geom,
    224 				   sector, slen, BUFFERSEG))
    225 		    errnum = ERR_READ;
    226 
    227 		  bufaddr = (char *) BUFFERADDR + byte_offset;
    228 		}
    229 	    }
    230 	  else
    231 	    buf_track = track;
    232 
    233 	  if ((buf_track == 0 || sector == 0)
    234 	      && (PC_SLICE_TYPE (BUFFERADDR, 0) == PC_SLICE_TYPE_EZD
    235 		  || PC_SLICE_TYPE (BUFFERADDR, 1) == PC_SLICE_TYPE_EZD
    236 		  || PC_SLICE_TYPE (BUFFERADDR, 2) == PC_SLICE_TYPE_EZD
    237 		  || PC_SLICE_TYPE (BUFFERADDR, 3) == PC_SLICE_TYPE_EZD))
    238 	    {
    239 	      /* This is a EZD disk map sector 0 to sector 1 */
    240 	      if (buf_track == 0 || slen >= 2)
    241 		{
    242 		  /* We already read the sector 1, copy it to sector 0 */
    243 		  memmove ((char *) BUFFERADDR,
    244 			   (char *) BUFFERADDR + buf_geom.sector_size,
    245 			   buf_geom.sector_size);
    246 		}
    247 	      else
    248 		{
    249 		  if (biosdisk (BIOSDISK_READ, drive, &buf_geom,
    250 				1, 1, BUFFERSEG))
    251 		    errnum = ERR_READ;
    252 		}
    253 	    }
    254 	}
    255 
    256       if (size > ((num_sect << sector_size_bits) - byte_offset))
    257 	size = (num_sect << sector_size_bits) - byte_offset;
    258 
    259       /*
    260        *  Instrumentation to tell which sectors were read and used.
    261        */
    262       if (disk_read_func)
    263 	{
    264 	  int sector_num = sector;
    265 	  int length = buf_geom.sector_size - byte_offset;
    266 	  if (length > size)
    267 	    length = size;
    268 	  (*disk_read_func) (sector_num++, byte_offset, length);
    269 	  length = size - length;
    270 	  if (length > 0)
    271 	    {
    272 	      while (length > buf_geom.sector_size)
    273 		{
    274 		  (*disk_read_func) (sector_num++, 0, buf_geom.sector_size);
    275 		  length -= buf_geom.sector_size;
    276 		}
    277 	      (*disk_read_func) (sector_num, 0, length);
    278 	    }
    279 	}
    280 
    281       grub_memmove (buf, bufaddr, size);
    282 
    283       buf += size;
    284       byte_len -= size;
    285       sector += num_sect;
    286       byte_offset = 0;
    287     }
    288 
    289   return (!errnum);
    290 }
    291 
    292 
    293 int
    294 devread (int sector, int byte_offset, int byte_len, char *buf)
    295 {
    296   /*
    297    *  Check partition boundaries
    298    */
    299   if (sector < 0
    300       || ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS))
    301 	  >= part_length))
    302     {
    303       errnum = ERR_OUTSIDE_PART;
    304       return 0;
    305     }
    306 
    307   /*
    308    *  Get the read to the beginning of a partition.
    309    */
    310   sector += byte_offset >> SECTOR_BITS;
    311   byte_offset &= SECTOR_SIZE - 1;
    312 
    313 #if !defined(STAGE1_5)
    314   if (disk_read_hook && debug)
    315     printf ("<%d, %d, %d>", sector, byte_offset, byte_len);
    316 #endif /* !STAGE1_5 */
    317 
    318   /*
    319    *  Call RAWREAD, which is very similar, but:
    320    *
    321    *    --  It takes an extra parameter, the drive number.
    322    *    --  It requires that "sector" is relative to the beginning
    323    *            of the disk.
    324    *    --  It doesn't handle offsets of more than 511 bytes into the
    325    *            sector.
    326    */
    327   return rawread (current_drive, part_start + sector, byte_offset,
    328 		  byte_len, buf);
    329 }
    330 
    331 #ifndef STAGE1_5
    332 int
    333 rawwrite (int drive, int sector, char *buf)
    334 {
    335   if (sector == 0)
    336     {
    337       if (biosdisk (BIOSDISK_READ, drive, &buf_geom, 0, 1, SCRATCHSEG))
    338 	{
    339 	  errnum = ERR_WRITE;
    340 	  return 0;
    341 	}
    342 
    343       if (PC_SLICE_TYPE (SCRATCHADDR, 0) == PC_SLICE_TYPE_EZD
    344 	  || PC_SLICE_TYPE (SCRATCHADDR, 1) == PC_SLICE_TYPE_EZD
    345 	  || PC_SLICE_TYPE (SCRATCHADDR, 2) == PC_SLICE_TYPE_EZD
    346 	  || PC_SLICE_TYPE (SCRATCHADDR, 3) == PC_SLICE_TYPE_EZD)
    347 	sector = 1;
    348     }
    349 
    350   memmove ((char *) SCRATCHADDR, buf, SECTOR_SIZE);
    351   if (biosdisk (BIOSDISK_WRITE, drive, &buf_geom,
    352 		sector, 1, SCRATCHSEG))
    353     {
    354       errnum = ERR_WRITE;
    355       return 0;
    356     }
    357 
    358   if (sector - sector % buf_geom.sectors == buf_track)
    359     /* Clear the cache.  */
    360     buf_track = -1;
    361 
    362   return 1;
    363 }
    364 
    365 int
    366 devwrite (int sector, int sector_count, char *buf)
    367 {
    368 #if defined(GRUB_UTIL) && defined(__linux__)
    369   if (current_partition != 0xFFFFFF
    370       && is_disk_device (device_map, current_drive))
    371     {
    372       /* If the grub shell is running under Linux and the user wants to
    373 	 embed a Stage 1.5 into a partition instead of a MBR, use system
    374 	 calls directly instead of biosdisk, because of the bug in
    375 	 Linux. *sigh*  */
    376       return write_to_partition (device_map, current_drive, current_partition,
    377 				 sector, sector_count, buf);
    378     }
    379   else
    380 #endif /* GRUB_UTIL && __linux__ */
    381     {
    382       int i;
    383 
    384       for (i = 0; i < sector_count; i++)
    385 	{
    386 	  if (! rawwrite (current_drive, part_start + sector + i,
    387 			  buf + (i << SECTOR_BITS)))
    388 	      return 0;
    389 
    390 	}
    391       return 1;
    392     }
    393 }
    394 
    395 static int
    396 sane_partition (void)
    397 {
    398   /* network drive */
    399   if (current_drive == NETWORK_DRIVE)
    400     return 1;
    401 
    402   if (!(current_partition & 0xFF000000uL)
    403       && ((current_drive & 0xFFFFFF7F) < 8
    404 	  || current_drive == cdrom_drive)
    405       && (current_partition & 0xFF) == 0xFF
    406       && ((current_partition & 0xFF00) == 0xFF00
    407 	  || (current_partition & 0xFF00) < 0x800)
    408       && ((current_partition >> 16) == 0xFF
    409 	  || (current_drive & 0x80)))
    410     return 1;
    411 
    412   errnum = ERR_DEV_VALUES;
    413   return 0;
    414 }
    415 #endif /* ! STAGE1_5 */
    416 
    417 static void
    418 attempt_mount (void)
    419 {
    420 #ifndef STAGE1_5
    421   for (fsys_type = 0; fsys_type < NUM_FSYS; fsys_type++)
    422     if ((fsys_table[fsys_type].mount_func) ())
    423       break;
    424 
    425   if (fsys_type == NUM_FSYS && errnum == ERR_NONE)
    426     errnum = ERR_FSYS_MOUNT;
    427 #else
    428   fsys_type = 0;
    429   if ((*(fsys_table[fsys_type].mount_func)) () != 1)
    430     {
    431       fsys_type = NUM_FSYS;
    432       errnum = ERR_FSYS_MOUNT;
    433     }
    434 #endif
    435 }
    436 
    437 
    438 #ifndef STAGE1_5
    439 /* Turn on the active flag for the partition SAVED_PARTITION in the
    440    drive SAVED_DRIVE. If an error occurs, return zero, otherwise return
    441    non-zero.  */
    442 int
    443 make_saved_active (void)
    444 {
    445   char mbr[512];
    446 
    447   if (saved_drive & 0x80)
    448     {
    449       /* Hard disk */
    450       int part = saved_partition >> 16;
    451 
    452       /* If the partition is not a primary partition, the active flag is
    453 	 meaningless. (XXX: Really?)  */
    454       if (part > 3)
    455 	{
    456 	  errnum = ERR_DEV_VALUES;
    457 	  return 0;
    458 	}
    459 
    460       /* Read the MBR in the scratch space.  */
    461       if (! rawread (saved_drive, 0, 0, SECTOR_SIZE, mbr))
    462 	return 0;
    463 
    464       /* If the partition is an extended partition, setting the active
    465 	 flag violates the specification by IBM.  */
    466       if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (mbr, part)))
    467 	{
    468 	  errnum = ERR_DEV_VALUES;
    469 	  return 0;
    470 	}
    471 
    472       /* Check if the active flag is disabled.  */
    473       if (PC_SLICE_FLAG (mbr, part) != PC_SLICE_FLAG_BOOTABLE)
    474 	{
    475 	  int i;
    476 
    477 	  /* Clear all the active flags in this table.  */
    478 	  for (i = 0; i < 4; i++)
    479 	    PC_SLICE_FLAG (mbr, i) = 0;
    480 
    481 	  /* Set the flag.  */
    482 	  PC_SLICE_FLAG (mbr, part) = PC_SLICE_FLAG_BOOTABLE;
    483 
    484 	  /* Write back the MBR.  */
    485 	  if (! rawwrite (saved_drive, 0, mbr))
    486 	    return 0;
    487 	}
    488     }
    489   else
    490     {
    491       /* If the drive is not a hard disk drive, you shouldn't call this
    492 	 function. (XXX: Should I just ignore this error?)  */
    493       errnum = ERR_DEV_VALUES;
    494       return 0;
    495     }
    496 
    497   return 1;
    498 }
    499 
    500 /* Hide/Unhide CURRENT_PARTITION.  */
    501 int
    502 set_partition_hidden_flag (int hidden)
    503 {
    504   unsigned long part = 0xFFFFFF;
    505   unsigned long start, len, offset, ext_offset;
    506   int entry, type;
    507   char mbr[512];
    508 
    509   /* The drive must be a hard disk.  */
    510   if (! (current_drive & 0x80))
    511     {
    512       errnum = ERR_BAD_ARGUMENT;
    513       return 1;
    514     }
    515 
    516   /* The partition must be a PC slice.  */
    517   if ((current_partition >> 16) == 0xFF
    518       || (current_partition & 0xFFFF) != 0xFFFF)
    519     {
    520       errnum = ERR_BAD_ARGUMENT;
    521       return 1;
    522     }
    523 
    524   /* Look for the partition.  */
    525   while (next_partition (current_drive, 0xFFFFFF, &part, &type,
    526 			 &start, &len, &offset, &entry,
    527 			 &ext_offset, mbr))
    528     {
    529       if (part == current_partition)
    530 	{
    531 	  /* Found.  */
    532 	  if (hidden)
    533 	    PC_SLICE_TYPE (mbr, entry) |= PC_SLICE_TYPE_HIDDEN_FLAG;
    534 	  else
    535 	    PC_SLICE_TYPE (mbr, entry) &= ~PC_SLICE_TYPE_HIDDEN_FLAG;
    536 
    537 	  /* Write back the MBR to the disk.  */
    538 	  buf_track = -1;
    539 	  if (! rawwrite (current_drive, offset, mbr))
    540 	    return 1;
    541 
    542 	  /* Succeed.  */
    543 	  return 0;
    544 	}
    545     }
    546 
    547   return 1;
    548 }
    549 
    550 
    551 static void
    552 check_and_print_mount (void)
    553 {
    554   attempt_mount ();
    555   if (errnum == ERR_FSYS_MOUNT)
    556     errnum = ERR_NONE;
    557   if (!errnum)
    558     print_fsys_type ();
    559   print_error ();
    560 }
    561 #endif /* STAGE1_5 */
    562 
    563 
    564 /* Get the information on next partition on the drive DRIVE.
    565    The caller must not modify the contents of the arguments when
    566    iterating this function. The partition representation in GRUB will
    567    be stored in *PARTITION. Likewise, the partition type in *TYPE, the
    568    start sector in *START, the length in *LEN, the offset of the
    569    partition table in *OFFSET, the entry number in the table in *ENTRY,
    570    the offset of the extended partition in *EXT_OFFSET.
    571    BUF is used to store a MBR, the boot sector of a partition, or
    572    a BSD label sector, and it must be at least 512 bytes length.
    573    When calling this function first, *PARTITION must be initialized to
    574    0xFFFFFF. The return value is zero if fails, otherwise non-zero.  */
    575 int
    576 next_partition (unsigned long drive, unsigned long dest,
    577 		unsigned long *partition, int *type,
    578 		unsigned long *start, unsigned long *len,
    579 		unsigned long *offset, int *entry,
    580 		unsigned long *ext_offset, char *buf)
    581 {
    582   /* Forward declarations.  */
    583   auto int next_bsd_partition (void);
    584   auto int next_pc_slice (void);
    585 
    586   /* Get next BSD partition in current PC slice.  */
    587   int next_bsd_partition (void)
    588     {
    589       int i;
    590       int bsd_part_no = (*partition & 0xFF00) >> 8;
    591 
    592       /* If this is the first time...  */
    593       if (bsd_part_no == 0xFF)
    594 	{
    595 	  /* Check if the BSD label is within current PC slice.  */
    596 	  if (*len < BSD_LABEL_SECTOR + 1)
    597 	    {
    598 	      errnum = ERR_BAD_PART_TABLE;
    599 	      return 0;
    600 	    }
    601 
    602 	  /* Read the BSD label.  */
    603 	  if (! rawread (drive, *start + BSD_LABEL_SECTOR,
    604 			 0, SECTOR_SIZE, buf))
    605 	    return 0;
    606 
    607 	  /* Check if it is valid.  */
    608 	  if (! BSD_LABEL_CHECK_MAG (buf))
    609 	    {
    610 	      errnum = ERR_BAD_PART_TABLE;
    611 	      return 0;
    612 	    }
    613 
    614 	  bsd_part_no = -1;
    615 	}
    616 
    617       /* Search next valid BSD partition.  */
    618       for (i = bsd_part_no + 1; i < BSD_LABEL_NPARTS (buf); i++)
    619 	{
    620 	  if (BSD_PART_TYPE (buf, i))
    621 	    {
    622 	      /* Note that *TYPE and *PARTITION were set
    623 		 for current PC slice.  */
    624 	      *type = (BSD_PART_TYPE (buf, i) << 8) | (*type & 0xFF);
    625 	      *start = BSD_PART_START (buf, i);
    626 	      *len = BSD_PART_LENGTH (buf, i);
    627 	      *partition = (*partition & 0xFF00FF) | (i << 8);
    628 
    629 #ifndef STAGE1_5
    630 	      /* XXX */
    631 	      if ((drive & 0x80) && BSD_LABEL_DTYPE (buf) == DTYPE_SCSI)
    632 		bsd_evil_hack = 4;
    633 #endif /* ! STAGE1_5 */
    634 
    635 	      return 1;
    636 	    }
    637 	}
    638 
    639       errnum = ERR_NO_PART;
    640       return 0;
    641     }
    642 
    643   /* Get next PC slice. Be careful of that this function may return
    644      an empty PC slice (i.e. a partition whose type is zero) as well.  */
    645   int next_pc_slice (void)
    646     {
    647       int pc_slice_no = (*partition & 0xFF0000) >> 16;
    648 
    649       /* If this is the first time...  */
    650       if (pc_slice_no == 0xFF)
    651 	{
    652 	  *offset = 0;
    653 	  *ext_offset = 0;
    654 	  *entry = -1;
    655 	  pc_slice_no = -1;
    656 	}
    657 
    658       /* Read the MBR or the boot sector of the extended partition.  */
    659       if (! rawread (drive, *offset, 0, SECTOR_SIZE, buf))
    660 	return 0;
    661 
    662       /* Check if it is valid.  */
    663       if (! PC_MBR_CHECK_SIG (buf))
    664 	{
    665 	  errnum = ERR_BAD_PART_TABLE;
    666 	  return 0;
    667 	}
    668 
    669       /* Increase the entry number.  */
    670       (*entry)++;
    671 
    672       /* If this is out of current partition table...  */
    673       if (*entry == PC_SLICE_MAX)
    674 	{
    675 	  int i;
    676 
    677 	  /* Search the first extended partition in current table.  */
    678 	  for (i = 0; i < PC_SLICE_MAX; i++)
    679 	    {
    680 	      if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (buf, i)))
    681 		{
    682 		  /* Found. Set the new offset and the entry number,
    683 		     and restart this function.  */
    684 		  *offset = *ext_offset + PC_SLICE_START (buf, i);
    685 		  if (! *ext_offset)
    686 		    *ext_offset = *offset;
    687 		  *entry = -1;
    688 		  return next_pc_slice ();
    689 		}
    690 	    }
    691 
    692 	  errnum = ERR_NO_PART;
    693 	  return 0;
    694 	}
    695 
    696       *type = PC_SLICE_TYPE (buf, *entry);
    697       *start = *offset + PC_SLICE_START (buf, *entry);
    698       *len = PC_SLICE_LENGTH (buf, *entry);
    699 
    700       /* The calculation of a PC slice number is complicated, because of
    701 	 the rather odd definition of extended partitions. Even worse,
    702 	 there is no guarantee that this is consistent with every
    703 	 operating systems. Uggh.  */
    704       if (pc_slice_no < PC_SLICE_MAX
    705 	  || (! IS_PC_SLICE_TYPE_EXTENDED (*type)
    706 	      && *type != PC_SLICE_TYPE_NONE))
    707 	pc_slice_no++;
    708 
    709       *partition = (pc_slice_no << 16) | 0xFFFF;
    710       return 1;
    711     }
    712 
    713   /* Start the body of this function.  */
    714 
    715 #ifndef STAGE1_5
    716   if (current_drive == NETWORK_DRIVE)
    717     return 0;
    718 #endif
    719 
    720   /* If previous partition is a BSD partition or a PC slice which
    721      contains BSD partitions...  */
    722   if ((*partition != 0xFFFFFF && IS_PC_SLICE_TYPE_BSD (*type & 0xff))
    723       || ! (drive & 0x80))
    724     {
    725       if (*type == PC_SLICE_TYPE_NONE)
    726 	*type = PC_SLICE_TYPE_FREEBSD;
    727 
    728       /* Get next BSD partition, if any.  */
    729       if (next_bsd_partition ())
    730 	return 1;
    731 
    732       /* If the destination partition is a BSD partition and current
    733 	 BSD partition has any error, abort the operation.  */
    734       if ((dest & 0xFF00) != 0xFF00
    735 	  && ((dest & 0xFF0000) == 0xFF0000
    736 	      || (dest & 0xFF0000) == (*partition & 0xFF0000)))
    737 	return 0;
    738 
    739       /* Ignore the error.  */
    740       errnum = ERR_NONE;
    741     }
    742 
    743   return next_pc_slice ();
    744 }
    745 
    746 #ifndef STAGE1_5
    747 static unsigned long cur_part_offset;
    748 static unsigned long cur_part_addr;
    749 #endif
    750 
    751 /* Open a partition.  */
    752 int
    753 real_open_partition (int flags)
    754 {
    755   unsigned long dest_partition = current_partition;
    756   unsigned long part_offset;
    757   unsigned long ext_offset;
    758   int entry;
    759   char buf[SECTOR_SIZE];
    760   int bsd_part, pc_slice;
    761 
    762   /* For simplicity.  */
    763   auto int next (void);
    764   int next (void)
    765     {
    766       int ret = next_partition (current_drive, dest_partition,
    767 				&current_partition, &current_slice,
    768 				&part_start, &part_length,
    769 				&part_offset, &entry, &ext_offset, buf);
    770       bsd_part = (current_partition >> 8) & 0xFF;
    771       pc_slice = current_partition >> 16;
    772       return ret;
    773     }
    774 
    775 #ifndef STAGE1_5
    776   /* network drive */
    777   if (current_drive == NETWORK_DRIVE)
    778     return 1;
    779 
    780   if (! sane_partition ())
    781     return 0;
    782 #endif
    783 
    784   bsd_evil_hack = 0;
    785   current_slice = 0;
    786   part_start = 0;
    787 
    788   /* Make sure that buf_geom is valid. */
    789   if (buf_drive != current_drive)
    790     {
    791       if (get_diskinfo (current_drive, &buf_geom))
    792 	{
    793 	  errnum = ERR_NO_DISK;
    794 	  return 0;
    795 	}
    796       buf_drive = current_drive;
    797       buf_track = -1;
    798     }
    799   part_length = buf_geom.total_sectors;
    800 
    801   /* If this is the whole disk, return here.  */
    802   if (! flags && current_partition == 0xFFFFFF)
    803     return 1;
    804 
    805   if (flags)
    806     dest_partition = 0xFFFFFF;
    807 
    808   /* Initialize CURRENT_PARTITION for next_partition.  */
    809   current_partition = 0xFFFFFF;
    810 
    811   while (next ())
    812     {
    813 #ifndef STAGE1_5
    814     loop_start:
    815 
    816       cur_part_offset = part_offset;
    817       cur_part_addr = BOOT_PART_TABLE + (entry << 4);
    818 #endif /* ! STAGE1_5 */
    819 
    820       /* If this is a valid partition...  */
    821       if (current_slice)
    822 	{
    823 #ifndef STAGE1_5
    824 	  /* Display partition information.  */
    825 	  if (flags && ! IS_PC_SLICE_TYPE_EXTENDED (current_slice))
    826 	    {
    827 	      if (! do_completion)
    828 		{
    829 		  if (current_drive & 0x80)
    830 		    grub_printf ("   Partition num: %d, ",
    831 				 current_partition >> 16);
    832 
    833 		  if (! IS_PC_SLICE_TYPE_BSD (current_slice))
    834 		    check_and_print_mount ();
    835 		  else
    836 		    {
    837 		      int got_part = 0;
    838 		      int saved_slice = current_slice;
    839 
    840 		      while (next ())
    841 			{
    842 			  if (bsd_part == 0xFF)
    843 			    break;
    844 
    845 			  if (! got_part)
    846 			    {
    847 			      grub_printf ("[BSD sub-partitions immediately follow]\n");
    848 			      got_part = 1;
    849 			    }
    850 
    851 			  grub_printf ("     BSD Partition num: \'%c\', ",
    852 				       bsd_part + 'a');
    853 			  check_and_print_mount ();
    854 			}
    855 
    856 		      if (! got_part)
    857 			grub_printf (" No BSD sub-partition found, partition type 0x%x\n",
    858 				     saved_slice);
    859 
    860 		      if (errnum)
    861 			{
    862 			  errnum = ERR_NONE;
    863 			  break;
    864 			}
    865 
    866 		      goto loop_start;
    867 		    }
    868 		}
    869 	      else
    870 		{
    871 		  if (bsd_part != 0xFF)
    872 		    {
    873 		      char str[16];
    874 
    875 		      if (! (current_drive & 0x80)
    876 			  || (dest_partition >> 16) == pc_slice)
    877 			grub_sprintf (str, "%c)", bsd_part + 'a');
    878 		      else
    879 			grub_sprintf (str, "%d,%c)",
    880 				      pc_slice, bsd_part + 'a');
    881 		      print_a_completion (str);
    882 		    }
    883 		  else if (! IS_PC_SLICE_TYPE_BSD (current_slice))
    884 		    {
    885 		      char str[8];
    886 
    887 		      grub_sprintf (str, "%d)", pc_slice);
    888 		      print_a_completion (str);
    889 		    }
    890 		}
    891 	    }
    892 
    893 	  errnum = ERR_NONE;
    894 #endif /* ! STAGE1_5 */
    895 
    896 	  /* Check if this is the destination partition.  */
    897 	  if (! flags
    898 	      && (dest_partition == current_partition
    899 		  || ((dest_partition >> 16) == 0xFF
    900 		      && ((dest_partition >> 8) & 0xFF) == bsd_part)))
    901 	    return 1;
    902 	}
    903     }
    904 
    905 #ifndef STAGE1_5
    906   if (flags)
    907     {
    908       if (! (current_drive & 0x80))
    909 	{
    910 	  current_partition = 0xFFFFFF;
    911 	  check_and_print_mount ();
    912 	}
    913 
    914       errnum = ERR_NONE;
    915       return 1;
    916     }
    917 #endif /* ! STAGE1_5 */
    918 
    919   return 0;
    920 }
    921 
    922 
    923 int
    924 open_partition (void)
    925 {
    926   return real_open_partition (0);
    927 }
    928 
    929 
    930 #ifndef STAGE1_5
    931 /* XX used for device completion in 'set_device' and 'print_completions' */
    932 static int incomplete, disk_choice;
    933 static enum
    934 {
    935   PART_UNSPECIFIED = 0,
    936   PART_DISK,
    937   PART_CHOSEN,
    938 }
    939 part_choice;
    940 #endif /* ! STAGE1_5 */
    941 
    942 char *
    943 set_device (char *device)
    944 {
    945 #ifdef STAGE1_5
    946     /* In Stage 1.5, the first 4 bytes of FILENAME has a device number.  */
    947   unsigned long dev = *((unsigned long *) device);
    948   int drive = (dev >> 24) & 0xFF;
    949   int partition = dev & 0xFFFFFF;
    950 
    951   /* If DRIVE is disabled, use SAVED_DRIVE instead.  */
    952   if (drive == GRUB_INVALID_DRIVE)
    953     current_drive = saved_drive;
    954   else
    955     current_drive = drive;
    956 
    957   /* The `partition' part must always have a valid number.  */
    958   current_partition = partition;
    959 
    960   return device + sizeof (unsigned long);
    961 
    962 #else /* ! STAGE1_5 */
    963 
    964   int result = 0;
    965 
    966   incomplete = 0;
    967   disk_choice = 1;
    968   part_choice = PART_UNSPECIFIED;
    969   current_drive = saved_drive;
    970   current_partition = 0xFFFFFF;
    971 
    972   if (*device == '(' && !*(device + 1))
    973     /* user has given '(' only, let disk_choice handle what disks we have */
    974     return device + 1;
    975 
    976   if (*device == '(' && *(++device))
    977     {
    978       if (*device != ',' && *device != ')')
    979 	{
    980 	  char ch = *device;
    981 #ifdef SUPPORT_NETBOOT
    982 	  if (*device == 'f' || *device == 'h'
    983 	      || (*device == 'n' && network_ready)
    984 	      || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE))
    985 #else
    986 	  if (*device == 'f' || *device == 'h'
    987 	      || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE))
    988 #endif /* SUPPORT_NETBOOT */
    989 	    {
    990 	      /* user has given '([fhn]', check for resp. add 'd' and
    991 		 let disk_choice handle what disks we have */
    992 	      if (!*(device + 1))
    993 		{
    994 		  device++;
    995 		  *device++ = 'd';
    996 		  *device = '\0';
    997 		  return device;
    998 		}
    999 	      else if (*(device + 1) == 'd' && !*(device + 2))
   1000 		return device + 2;
   1001 	    }
   1002 
   1003 	  if ((*device == 'f'
   1004 	       || *device == 'h'
   1005 #ifdef SUPPORT_NETBOOT
   1006 	       || (*device == 'n' && network_ready)
   1007 #endif
   1008 	       || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE))
   1009 	      && (device += 2, (*(device - 1) != 'd')))
   1010 	    errnum = ERR_NUMBER_PARSING;
   1011 
   1012 #ifdef SUPPORT_NETBOOT
   1013 	  if (ch == 'n' && network_ready)
   1014 	    current_drive = NETWORK_DRIVE;
   1015 	  else
   1016 #endif /* SUPPORT_NETBOOT */
   1017 	    {
   1018 	      if (ch == 'c' && cdrom_drive != GRUB_INVALID_DRIVE)
   1019 		current_drive = cdrom_drive;
   1020 	      else
   1021 		{
   1022 		  safe_parse_maxint (&device, (int *) &current_drive);
   1023 
   1024 		  disk_choice = 0;
   1025 		  if (ch == 'h')
   1026 		    current_drive += 0x80;
   1027 		}
   1028 	    }
   1029 	}
   1030 
   1031       if (errnum)
   1032 	return 0;
   1033 
   1034       if (*device == ')')
   1035 	{
   1036 	  part_choice = PART_CHOSEN;
   1037 	  result = 1;
   1038 	}
   1039       else if (*device == ',')
   1040 	{
   1041 	  /* Either an absolute PC or BSD partition. */
   1042 	  disk_choice = 0;
   1043 	  part_choice ++;
   1044 	  device++;
   1045 
   1046 	  if (*device >= '0' && *device <= '9')
   1047 	    {
   1048 	      part_choice ++;
   1049 	      current_partition = 0;
   1050 
   1051 	      if (!(current_drive & 0x80)
   1052 		  || !safe_parse_maxint (&device, (int *) &current_partition)
   1053 		  || current_partition > 254)
   1054 		{
   1055 		  errnum = ERR_DEV_FORMAT;
   1056 		  return 0;
   1057 		}
   1058 
   1059 	      current_partition = (current_partition << 16) + 0xFFFF;
   1060 
   1061 	      if (*device == ',')
   1062 		device++;
   1063 
   1064 	      if (*device >= 'a' && *device <= 'h')
   1065 		{
   1066 		  current_partition = (((*(device++) - 'a') << 8)
   1067 				       | (current_partition & 0xFF00FF));
   1068 		}
   1069 	    }
   1070 	  else if (*device >= 'a' && *device <= 'h')
   1071 	    {
   1072 	      part_choice ++;
   1073 	      current_partition = ((*(device++) - 'a') << 8) | 0xFF00FF;
   1074 	    }
   1075 
   1076 	  if (*device == ')')
   1077 	    {
   1078 	      if (part_choice == PART_DISK)
   1079 		{
   1080 		  current_partition = saved_partition;
   1081 		  part_choice ++;
   1082 		}
   1083 
   1084 	      result = 1;
   1085 	    }
   1086 	}
   1087     }
   1088 
   1089   if (! sane_partition ())
   1090     return 0;
   1091 
   1092   if (result)
   1093     return device + 1;
   1094   else
   1095     {
   1096       if (!*device)
   1097 	incomplete = 1;
   1098       errnum = ERR_DEV_FORMAT;
   1099     }
   1100 
   1101   return 0;
   1102 
   1103 #endif /* ! STAGE1_5 */
   1104 }
   1105 
   1106 /*
   1107  *  This performs a "mount" on the current device, both drive and partition
   1108  *  number.
   1109  */
   1110 
   1111 int
   1112 open_device (void)
   1113 {
   1114   if (open_partition ())
   1115     attempt_mount ();
   1116 
   1117   if (errnum != ERR_NONE)
   1118     return 0;
   1119 
   1120   return 1;
   1121 }
   1122 
   1123 
   1124 #ifndef STAGE1_5
   1125 int
   1126 set_bootdev (int hdbias)
   1127 {
   1128   int i, j;
   1129 
   1130   /* Copy the boot partition information to 0x7be-0x7fd for chain-loading.  */
   1131   if ((saved_drive & 0x80) && cur_part_addr)
   1132     {
   1133       if (rawread (saved_drive, cur_part_offset,
   1134 		   0, SECTOR_SIZE, (char *) SCRATCHADDR))
   1135 	{
   1136 	  char *dst, *src;
   1137 
   1138 	  /* Need only the partition table.
   1139 	     XXX: We cannot use grub_memmove because BOOT_PART_TABLE
   1140 	     (0x07be) is less than 0x1000.  */
   1141 	  dst = (char *) BOOT_PART_TABLE;
   1142 	  src = (char *) SCRATCHADDR + BOOTSEC_PART_OFFSET;
   1143 	  while (dst < (char *) BOOT_PART_TABLE + BOOTSEC_PART_LENGTH)
   1144 	    *dst++ = *src++;
   1145 
   1146 	  /* Set the active flag of the booted partition.  */
   1147 	  for (i = 0; i < 4; i++)
   1148 	    PC_SLICE_FLAG (BOOT_PART_TABLE, i) = 0;
   1149 
   1150 	  *((unsigned char *) cur_part_addr) = PC_SLICE_FLAG_BOOTABLE;
   1151 	  boot_part_addr = cur_part_addr;
   1152 	}
   1153       else
   1154 	return 0;
   1155     }
   1156 
   1157   /*
   1158    *  Set BSD boot device.
   1159    */
   1160   i = (saved_partition >> 16) + 2;
   1161   if (saved_partition == 0xFFFFFF)
   1162     i = 1;
   1163   else if ((saved_partition >> 16) == 0xFF)
   1164     i = 0;
   1165 
   1166   /* FIXME: extremely evil hack!!! */
   1167   j = 2;
   1168   if (saved_drive & 0x80)
   1169     j = bsd_evil_hack;
   1170 
   1171   return MAKEBOOTDEV (j, (i >> 4), (i & 0xF),
   1172 		      ((saved_drive - hdbias) & 0x7F),
   1173 		      ((saved_partition >> 8) & 0xFF));
   1174 }
   1175 #endif /* STAGE1_5 */
   1176 
   1177 
   1178 static char *
   1179 setup_part (char *filename)
   1180 {
   1181 #ifdef STAGE1_5
   1182 
   1183   if (! (filename = set_device (filename)))
   1184     {
   1185       current_drive = GRUB_INVALID_DRIVE;
   1186       return 0;
   1187     }
   1188 
   1189 # ifndef NO_BLOCK_FILES
   1190   if (*filename != '/')
   1191     open_partition ();
   1192   else
   1193 # endif /* ! NO_BLOCK_FILES */
   1194     open_device ();
   1195 
   1196 #else /* ! STAGE1_5 */
   1197 
   1198   if (*filename == '(')
   1199     {
   1200       if ((filename = set_device (filename)) == 0)
   1201 	{
   1202 	  current_drive = GRUB_INVALID_DRIVE;
   1203 	  return 0;
   1204 	}
   1205 # ifndef NO_BLOCK_FILES
   1206       if (*filename != '/')
   1207 	open_partition ();
   1208       else
   1209 # endif /* ! NO_BLOCK_FILES */
   1210 	open_device ();
   1211     }
   1212   else if (saved_drive != current_drive
   1213 	   || saved_partition != current_partition
   1214 	   || (*filename == '/' && fsys_type == NUM_FSYS)
   1215 	   || buf_drive == -1)
   1216     {
   1217       current_drive = saved_drive;
   1218       current_partition = saved_partition;
   1219       /* allow for the error case of "no filesystem" after the partition
   1220          is found.  This makes block files work fine on no filesystem */
   1221 # ifndef NO_BLOCK_FILES
   1222       if (*filename != '/')
   1223 	open_partition ();
   1224       else
   1225 # endif /* ! NO_BLOCK_FILES */
   1226 	open_device ();
   1227     }
   1228 
   1229 #endif /* ! STAGE1_5 */
   1230 
   1231   if (errnum && (*filename == '/' || errnum != ERR_FSYS_MOUNT))
   1232     return 0;
   1233   else
   1234     errnum = 0;
   1235 
   1236 #ifndef STAGE1_5
   1237   if (!sane_partition ())
   1238     return 0;
   1239 #endif
   1240 
   1241   return filename;
   1242 }
   1243 
   1244 
   1245 #ifndef STAGE1_5
   1246 /*
   1247  *  This prints the filesystem type or gives relevant information.
   1248  */
   1249 
   1250 void
   1251 print_fsys_type (void)
   1252 {
   1253   if (! do_completion)
   1254     {
   1255       printf (" Filesystem type ");
   1256 
   1257       if (fsys_type != NUM_FSYS)
   1258 	printf ("is %s, ", fsys_table[fsys_type].name);
   1259       else
   1260 	printf ("unknown, ");
   1261 
   1262       if (current_partition == 0xFFFFFF)
   1263 	printf ("using whole disk\n");
   1264       else
   1265 	printf ("partition type 0x%x\n", current_slice & 0xFF);
   1266     }
   1267 }
   1268 #endif /* STAGE1_5 */
   1269 
   1270 #ifndef STAGE1_5
   1271 /* If DO_COMPLETION is true, just print NAME. Otherwise save the unique
   1272    part into UNIQUE_STRING.  */
   1273 void
   1274 print_a_completion (char *name)
   1275 {
   1276   /* If NAME is "." or "..", do not count it.  */
   1277   if (grub_strcmp (name, ".") == 0 || grub_strcmp (name, "..") == 0)
   1278     return;
   1279 
   1280   if (do_completion)
   1281     {
   1282       char *buf = unique_string;
   1283 
   1284       if (! unique)
   1285 	while ((*buf++ = *name++))
   1286 	  ;
   1287       else
   1288 	{
   1289 	  while (*buf && (*buf == *name))
   1290 	    {
   1291 	      buf++;
   1292 	      name++;
   1293 	    }
   1294 	  /* mismatch, strip it.  */
   1295 	  *buf = '\0';
   1296 	}
   1297     }
   1298   else
   1299     grub_printf (" %s", name);
   1300 
   1301   unique++;
   1302 }
   1303 
   1304 /*
   1305  *  This lists the possible completions of a device string, filename, or
   1306  *  any sane combination of the two.
   1307  */
   1308 
   1309 int
   1310 print_completions (int is_filename, int is_completion)
   1311 {
   1312   char *buf = (char *) COMPLETION_BUF;
   1313   char *ptr = buf;
   1314 
   1315   unique_string = (char *) UNIQUE_BUF;
   1316   *unique_string = 0;
   1317   unique = 0;
   1318   do_completion = is_completion;
   1319 
   1320   if (! is_filename)
   1321     {
   1322       /* Print the completions of builtin commands.  */
   1323       struct builtin **builtin;
   1324 
   1325       if (! is_completion)
   1326 	grub_printf (" Possible commands are:");
   1327 
   1328       for (builtin = builtin_table; (*builtin); builtin++)
   1329 	{
   1330 	  /* If *BUILTIN cannot be run in the command-line, skip it.  */
   1331 	  if (! ((*builtin)->flags & BUILTIN_CMDLINE))
   1332 	    continue;
   1333 
   1334 	  if (substring (buf, (*builtin)->name) <= 0)
   1335 	    print_a_completion ((*builtin)->name);
   1336 	}
   1337 
   1338       if (is_completion && *unique_string)
   1339 	{
   1340 	  if (unique == 1)
   1341 	    {
   1342 	      char *u = unique_string + grub_strlen (unique_string);
   1343 
   1344 	      *u++ = ' ';
   1345 	      *u = 0;
   1346 	    }
   1347 
   1348 	  grub_strcpy (buf, unique_string);
   1349 	}
   1350 
   1351       if (! is_completion)
   1352 	grub_putchar ('\n');
   1353 
   1354       print_error ();
   1355       do_completion = 0;
   1356       if (errnum)
   1357 	return -1;
   1358       else
   1359 	return unique - 1;
   1360     }
   1361 
   1362   if (*buf == '/' || (ptr = set_device (buf)) || incomplete)
   1363     {
   1364       errnum = 0;
   1365 
   1366       if (*buf == '(' && (incomplete || ! *ptr))
   1367 	{
   1368 	  if (! part_choice)
   1369 	    {
   1370 	      /* disk completions */
   1371 	      int disk_no, i, j;
   1372 	      struct geometry geom;
   1373 
   1374 	      if (! is_completion)
   1375 		grub_printf (" Possible disks are: ");
   1376 
   1377 	      if (!ptr
   1378 		  || *(ptr-1) != 'd'
   1379 #ifdef SUPPORT_NETBOOT
   1380 		  || *(ptr-2) != 'n'
   1381 #endif /* SUPPORT_NETBOOT */
   1382 		  || *(ptr-2) != 'c')
   1383 		{
   1384 		  for (i = (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'h') ? 1:0);
   1385 		       i < (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'f') ? 1:2);
   1386 		       i++)
   1387 		    {
   1388 		      for (j = 0; j < 8; j++)
   1389 			{
   1390 			  disk_no = (i * 0x80) + j;
   1391 			  if ((disk_choice || disk_no == current_drive)
   1392 			      && ! get_diskinfo (disk_no, &geom))
   1393 			    {
   1394 			      char dev_name[8];
   1395 
   1396 			      grub_sprintf (dev_name, "%cd%d", i ? 'h':'f', j);
   1397 			      print_a_completion (dev_name);
   1398 			    }
   1399 			}
   1400 		    }
   1401 		}
   1402 
   1403 	      if (cdrom_drive != GRUB_INVALID_DRIVE
   1404 		  && (disk_choice || cdrom_drive == current_drive)
   1405 		  && (!ptr
   1406 		      || *(ptr-1) == '('
   1407 		      || (*(ptr-1) == 'd' && *(ptr-2) == 'c')))
   1408 		print_a_completion ("cd");
   1409 
   1410 # ifdef SUPPORT_NETBOOT
   1411 	      if (network_ready
   1412 		  && (disk_choice || NETWORK_DRIVE == current_drive)
   1413 		  && (!ptr
   1414 		      || *(ptr-1) == '('
   1415 		      || (*(ptr-1) == 'd' && *(ptr-2) == 'n')))
   1416 		print_a_completion ("nd");
   1417 # endif /* SUPPORT_NETBOOT */
   1418 
   1419 	      if (is_completion && *unique_string)
   1420 		{
   1421 		  ptr = buf;
   1422 		  while (*ptr != '(')
   1423 		    ptr--;
   1424 		  ptr++;
   1425 		  grub_strcpy (ptr, unique_string);
   1426 		  if (unique == 1)
   1427 		    {
   1428 		      ptr += grub_strlen (ptr);
   1429 		      if (*unique_string == 'h')
   1430 			{
   1431 			  *ptr++ = ',';
   1432 			  *ptr = 0;
   1433 			}
   1434 		      else
   1435 			{
   1436 			  *ptr++ = ')';
   1437 			  *ptr = 0;
   1438 			}
   1439 		    }
   1440 		}
   1441 
   1442 	      if (! is_completion)
   1443 		grub_putchar ('\n');
   1444 	    }
   1445 	  else
   1446 	    {
   1447 	      /* partition completions */
   1448 	      if (part_choice == PART_CHOSEN
   1449 		  && open_partition ()
   1450 		  && ! IS_PC_SLICE_TYPE_BSD (current_slice))
   1451 		{
   1452 		  unique = 1;
   1453 		  ptr = buf + grub_strlen (buf);
   1454 		  if (*(ptr - 1) != ')')
   1455 		    {
   1456 		      *ptr++ = ')';
   1457 		      *ptr = 0;
   1458 		    }
   1459 		}
   1460 	      else
   1461 		{
   1462 		  if (! is_completion)
   1463 		    grub_printf (" Possible partitions are:\n");
   1464 		  real_open_partition (1);
   1465 
   1466 		  if (is_completion && *unique_string)
   1467 		    {
   1468 		      ptr = buf;
   1469 		      while (*ptr++ != ',')
   1470 			;
   1471 		      grub_strcpy (ptr, unique_string);
   1472 		    }
   1473 		}
   1474 	    }
   1475 	}
   1476       else if (ptr && *ptr == '/')
   1477 	{
   1478 	  /* filename completions */
   1479 	  if (! is_completion)
   1480 	    grub_printf (" Possible files are:");
   1481 
   1482 	  dir (buf);
   1483 
   1484 	  if (is_completion && *unique_string)
   1485 	    {
   1486 	      ptr += grub_strlen (ptr);
   1487 	      while (*ptr != '/')
   1488 		ptr--;
   1489 	      ptr++;
   1490 
   1491 	      grub_strcpy (ptr, unique_string);
   1492 
   1493 	      if (unique == 1)
   1494 		{
   1495 		  ptr += grub_strlen (unique_string);
   1496 
   1497 		  /* Check if the file UNIQUE_STRING is a directory.  */
   1498 		  *ptr = '/';
   1499 		  *(ptr + 1) = 0;
   1500 
   1501 		  dir (buf);
   1502 
   1503 		  /* Restore the original unique value.  */
   1504 		  unique = 1;
   1505 
   1506 		  if (errnum)
   1507 		    {
   1508 		      /* Regular file */
   1509 		      errnum = 0;
   1510 		      *ptr = ' ';
   1511 		      *(ptr + 1) = 0;
   1512 		    }
   1513 		}
   1514 	    }
   1515 
   1516 	  if (! is_completion)
   1517 	    grub_putchar ('\n');
   1518 	}
   1519       else
   1520 	errnum = ERR_BAD_FILENAME;
   1521     }
   1522 
   1523   print_error ();
   1524   do_completion = 0;
   1525   if (errnum)
   1526     return -1;
   1527   else
   1528     return unique - 1;
   1529 }
   1530 #endif /* STAGE1_5 */
   1531 
   1532 
   1533 /*
   1534  *  This is the generic file open function.
   1535  */
   1536 
   1537 int
   1538 grub_open (char *filename)
   1539 {
   1540 #ifndef NO_DECOMPRESSION
   1541   compressed_file = 0;
   1542 #endif /* NO_DECOMPRESSION */
   1543 
   1544   /* if any "dir" function uses/sets filepos, it must
   1545      set it to zero before returning if opening a file! */
   1546   filepos = 0;
   1547 
   1548   if (!(filename = setup_part (filename)))
   1549     return 0;
   1550 
   1551 #ifndef NO_BLOCK_FILES
   1552   block_file = 0;
   1553 #endif /* NO_BLOCK_FILES */
   1554 
   1555   /* This accounts for partial filesystem implementations. */
   1556   fsmax = MAXINT;
   1557 
   1558   if (*filename != '/')
   1559     {
   1560 #ifndef NO_BLOCK_FILES
   1561       char *ptr = filename;
   1562       int tmp, list_addr = BLK_BLKLIST_START;
   1563       filemax = 0;
   1564 
   1565       while (list_addr < BLK_MAX_ADDR)
   1566 	{
   1567 	  tmp = 0;
   1568 	  safe_parse_maxint (&ptr, &tmp);
   1569 	  errnum = 0;
   1570 
   1571 	  if (*ptr != '+')
   1572 	    {
   1573 	      if ((*ptr && *ptr != '/' && !isspace (*ptr))
   1574 		  || tmp == 0 || tmp > filemax)
   1575 		errnum = ERR_BAD_FILENAME;
   1576 	      else
   1577 		filemax = tmp;
   1578 
   1579 	      break;
   1580 	    }
   1581 
   1582 	  /* since we use the same filesystem buffer, mark it to
   1583 	     be remounted */
   1584 	  fsys_type = NUM_FSYS;
   1585 
   1586 	  BLK_BLKSTART (list_addr) = tmp;
   1587 	  ptr++;
   1588 
   1589 	  if (!safe_parse_maxint (&ptr, &tmp)
   1590 	      || tmp == 0
   1591 	      || (*ptr && *ptr != ',' && *ptr != '/' && !isspace (*ptr)))
   1592 	    {
   1593 	      errnum = ERR_BAD_FILENAME;
   1594 	      break;
   1595 	    }
   1596 
   1597 	  BLK_BLKLENGTH (list_addr) = tmp;
   1598 
   1599 	  filemax += (tmp * SECTOR_SIZE);
   1600 	  list_addr += BLK_BLKLIST_INC_VAL;
   1601 
   1602 	  if (*ptr != ',')
   1603 	    break;
   1604 
   1605 	  ptr++;
   1606 	}
   1607 
   1608       if (list_addr < BLK_MAX_ADDR && ptr != filename && !errnum)
   1609 	{
   1610 	  block_file = 1;
   1611 	  BLK_CUR_FILEPOS = 0;
   1612 	  BLK_CUR_BLKLIST = BLK_BLKLIST_START;
   1613 	  BLK_CUR_BLKNUM = 0;
   1614 
   1615 #ifndef NO_DECOMPRESSION
   1616 	  return gunzip_test_header ();
   1617 #else /* NO_DECOMPRESSION */
   1618 	  return 1;
   1619 #endif /* NO_DECOMPRESSION */
   1620 	}
   1621 #else /* NO_BLOCK_FILES */
   1622       errnum = ERR_BAD_FILENAME;
   1623 #endif /* NO_BLOCK_FILES */
   1624     }
   1625 
   1626   if (!errnum && fsys_type == NUM_FSYS)
   1627     errnum = ERR_FSYS_MOUNT;
   1628 
   1629 # ifndef STAGE1_5
   1630   /* set "dir" function to open a file */
   1631   print_possibilities = 0;
   1632 # endif
   1633 
   1634   if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename))
   1635     {
   1636 #ifndef NO_DECOMPRESSION
   1637       return gunzip_test_header ();
   1638 #else /* NO_DECOMPRESSION */
   1639       return 1;
   1640 #endif /* NO_DECOMPRESSION */
   1641     }
   1642 
   1643   return 0;
   1644 }
   1645 
   1646 
   1647 int
   1648 grub_read (char *buf, int len)
   1649 {
   1650   /* Make sure "filepos" is a sane value */
   1651   if ((filepos < 0) || (filepos > filemax))
   1652     filepos = filemax;
   1653 
   1654   /* Make sure "len" is a sane value */
   1655   if ((len < 0) || (len > (filemax - filepos)))
   1656     len = filemax - filepos;
   1657 
   1658   /* if target file position is past the end of
   1659      the supported/configured filesize, then
   1660      there is an error */
   1661   if (filepos + len > fsmax)
   1662     {
   1663       errnum = ERR_FILELENGTH;
   1664       return 0;
   1665     }
   1666 
   1667 #ifndef NO_DECOMPRESSION
   1668   if (compressed_file)
   1669     return gunzip_read (buf, len);
   1670 #endif /* NO_DECOMPRESSION */
   1671 
   1672 #ifndef NO_BLOCK_FILES
   1673   if (block_file)
   1674     {
   1675       int size, off, ret = 0;
   1676 
   1677       while (len && !errnum)
   1678 	{
   1679 	  /* we may need to look for the right block in the list(s) */
   1680 	  if (filepos < BLK_CUR_FILEPOS)
   1681 	    {
   1682 	      BLK_CUR_FILEPOS = 0;
   1683 	      BLK_CUR_BLKLIST = BLK_BLKLIST_START;
   1684 	      BLK_CUR_BLKNUM = 0;
   1685 	    }
   1686 
   1687 	  /* run BLK_CUR_FILEPOS up to filepos */
   1688 	  while (filepos > BLK_CUR_FILEPOS)
   1689 	    {
   1690 	      if ((filepos - (BLK_CUR_FILEPOS & ~(SECTOR_SIZE - 1)))
   1691 		  >= SECTOR_SIZE)
   1692 		{
   1693 		  BLK_CUR_FILEPOS += SECTOR_SIZE;
   1694 		  BLK_CUR_BLKNUM++;
   1695 
   1696 		  if (BLK_CUR_BLKNUM >= BLK_BLKLENGTH (BLK_CUR_BLKLIST))
   1697 		    {
   1698 		      BLK_CUR_BLKLIST += BLK_BLKLIST_INC_VAL;
   1699 		      BLK_CUR_BLKNUM = 0;
   1700 		    }
   1701 		}
   1702 	      else
   1703 		BLK_CUR_FILEPOS = filepos;
   1704 	    }
   1705 
   1706 	  off = filepos & (SECTOR_SIZE - 1);
   1707 	  size = ((BLK_BLKLENGTH (BLK_CUR_BLKLIST) - BLK_CUR_BLKNUM)
   1708 		  * SECTOR_SIZE) - off;
   1709 	  if (size > len)
   1710 	    size = len;
   1711 
   1712 	  disk_read_func = disk_read_hook;
   1713 
   1714 	  /* read current block and put it in the right place in memory */
   1715 	  devread (BLK_BLKSTART (BLK_CUR_BLKLIST) + BLK_CUR_BLKNUM,
   1716 		   off, size, buf);
   1717 
   1718 	  disk_read_func = NULL;
   1719 
   1720 	  len -= size;
   1721 	  filepos += size;
   1722 	  ret += size;
   1723 	  buf += size;
   1724 	}
   1725 
   1726       if (errnum)
   1727 	ret = 0;
   1728 
   1729       return ret;
   1730     }
   1731 #endif /* NO_BLOCK_FILES */
   1732 
   1733   if (fsys_type == NUM_FSYS)
   1734     {
   1735       errnum = ERR_FSYS_MOUNT;
   1736       return 0;
   1737     }
   1738 
   1739   return (*(fsys_table[fsys_type].read_func)) (buf, len);
   1740 }
   1741 
   1742 #ifndef STAGE1_5
   1743 /* Reposition a file offset.  */
   1744 int
   1745 grub_seek (int offset)
   1746 {
   1747   if (offset > filemax || offset < 0)
   1748     return -1;
   1749 
   1750   filepos = offset;
   1751   return offset;
   1752 }
   1753 
   1754 int
   1755 dir (char *dirname)
   1756 {
   1757 #ifndef NO_DECOMPRESSION
   1758   compressed_file = 0;
   1759 #endif /* NO_DECOMPRESSION */
   1760 
   1761   if (!(dirname = setup_part (dirname)))
   1762     return 0;
   1763 
   1764   if (*dirname != '/')
   1765     errnum = ERR_BAD_FILENAME;
   1766 
   1767   if (fsys_type == NUM_FSYS)
   1768     errnum = ERR_FSYS_MOUNT;
   1769 
   1770   if (errnum)
   1771     return 0;
   1772 
   1773   /* set "dir" function to list completions */
   1774   print_possibilities = 1;
   1775 
   1776   return (*(fsys_table[fsys_type].dir_func)) (dirname);
   1777 }
   1778 #endif /* STAGE1_5 */
   1779 
   1780 void
   1781 grub_close (void)
   1782 {
   1783 #ifndef NO_BLOCK_FILES
   1784   if (block_file)
   1785     return;
   1786 #endif /* NO_BLOCK_FILES */
   1787 
   1788   if (fsys_table[fsys_type].close_func != 0)
   1789     (*(fsys_table[fsys_type].close_func)) ();
   1790 }
   1791