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