xref: /illumos-gate/usr/src/grub/grub-0.97/stage2/disk_io.c (revision 99114ab6663dd12ed5ff3c0da58de645e7ebaff4)
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   {
435     /*
436      * (re)set errnum to 0 in order to clear any state that may have
437      * been left from a previous mount (or other) routine.
438      */
439     errnum = 0;
440     if ((fsys_table[fsys_type].mount_func) ())
441       break;
442   }
443 
444   if (fsys_type == NUM_FSYS && errnum == ERR_NONE)
445     errnum = ERR_FSYS_MOUNT;
446 #else
447   fsys_type = 0;
448   if ((*(fsys_table[fsys_type].mount_func)) () != 1)
449     {
450       fsys_type = NUM_FSYS;
451       errnum = ERR_FSYS_MOUNT;
452     }
453 #endif
454 }
455 
456 
457 #ifndef STAGE1_5
458 /* Turn on the active flag for the partition SAVED_PARTITION in the
459    drive SAVED_DRIVE. If an error occurs, return zero, otherwise return
460    non-zero.  */
461 int
462 make_saved_active (void)
463 {
464   char mbr[512];
465 
466   if (saved_drive & 0x80)
467     {
468       /* Hard disk */
469       int part = saved_partition >> 16;
470 
471       /* If the partition is not a primary partition, the active flag is
472 	 meaningless. (XXX: Really?)  */
473       if (part > 3)
474 	{
475 	  errnum = ERR_DEV_VALUES;
476 	  return 0;
477 	}
478 
479       /* Read the MBR in the scratch space.  */
480       if (! rawread (saved_drive, 0, 0, SECTOR_SIZE, mbr))
481 	return 0;
482 
483       /* If the partition is an extended partition, setting the active
484 	 flag violates the specification by IBM.  */
485       if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (mbr, part)))
486 	{
487 	  errnum = ERR_DEV_VALUES;
488 	  return 0;
489 	}
490 
491       /* Check if the active flag is disabled.  */
492       if (PC_SLICE_FLAG (mbr, part) != PC_SLICE_FLAG_BOOTABLE)
493 	{
494 	  int i;
495 
496 	  /* Clear all the active flags in this table.  */
497 	  for (i = 0; i < 4; i++)
498 	    PC_SLICE_FLAG (mbr, i) = 0;
499 
500 	  /* Set the flag.  */
501 	  PC_SLICE_FLAG (mbr, part) = PC_SLICE_FLAG_BOOTABLE;
502 
503 	  /* Write back the MBR.  */
504 	  if (! rawwrite (saved_drive, 0, mbr))
505 	    return 0;
506 	}
507     }
508   else
509     {
510       /* If the drive is not a hard disk drive, you shouldn't call this
511 	 function. (XXX: Should I just ignore this error?)  */
512       errnum = ERR_DEV_VALUES;
513       return 0;
514     }
515 
516   return 1;
517 }
518 
519 /* Hide/Unhide CURRENT_PARTITION.  */
520 int
521 set_partition_hidden_flag (int hidden)
522 {
523   unsigned long part = 0xFFFFFF;
524   unsigned long start, len, offset, ext_offset;
525   int entry, type;
526   char mbr[512];
527 
528   /* The drive must be a hard disk.  */
529   if (! (current_drive & 0x80))
530     {
531       errnum = ERR_BAD_ARGUMENT;
532       return 1;
533     }
534 
535   /* The partition must be a PC slice.  */
536   if ((current_partition >> 16) == 0xFF
537       || (current_partition & 0xFFFF) != 0xFFFF)
538     {
539       errnum = ERR_BAD_ARGUMENT;
540       return 1;
541     }
542 
543   /* Look for the partition.  */
544   while (next_partition (current_drive, 0xFFFFFF, &part, &type,
545 			 &start, &len, &offset, &entry,
546 			 &ext_offset, mbr))
547     {
548       if (part == current_partition)
549 	{
550 	  /* Found.  */
551 	  if (hidden)
552 	    PC_SLICE_TYPE (mbr, entry) |= PC_SLICE_TYPE_HIDDEN_FLAG;
553 	  else
554 	    PC_SLICE_TYPE (mbr, entry) &= ~PC_SLICE_TYPE_HIDDEN_FLAG;
555 
556 	  /* Write back the MBR to the disk.  */
557 	  buf_track = BUF_CACHE_INVALID;
558 	  if (! rawwrite (current_drive, offset, mbr))
559 	    return 1;
560 
561 	  /* Succeed.  */
562 	  return 0;
563 	}
564     }
565 
566   return 1;
567 }
568 
569 
570 static void
571 check_and_print_mount (void)
572 {
573   attempt_mount ();
574   if (errnum == ERR_FSYS_MOUNT)
575     errnum = ERR_NONE;
576   if (!errnum)
577     print_fsys_type ();
578   print_error ();
579 }
580 #endif /* STAGE1_5 */
581 
582 
583 /* Get the information on next partition on the drive DRIVE.
584    The caller must not modify the contents of the arguments when
585    iterating this function. The partition representation in GRUB will
586    be stored in *PARTITION. Likewise, the partition type in *TYPE, the
587    start sector in *START, the length in *LEN, the offset of the
588    partition table in *OFFSET, the entry number in the table in *ENTRY,
589    the offset of the extended partition in *EXT_OFFSET.
590    BUF is used to store a MBR, the boot sector of a partition, or
591    a BSD label sector, and it must be at least 512 bytes length.
592    When calling this function first, *PARTITION must be initialized to
593    0xFFFFFF. The return value is zero if fails, otherwise non-zero.  */
594 int
595 next_partition (unsigned long drive, unsigned long dest,
596 		unsigned long *partition, int *type,
597 		unsigned long *start, unsigned long *len,
598 		unsigned long *offset, int *entry,
599 		unsigned long *ext_offset, char *buf)
600 {
601   /* Forward declarations.  */
602   auto int next_bsd_partition (void);
603   auto int next_solaris_partition(void);
604   auto int next_pc_slice (void);
605 
606   /* Get next BSD partition in current PC slice.  */
607   int next_bsd_partition (void)
608     {
609       int i;
610       int bsd_part_no = (*partition & 0xFF00) >> 8;
611 
612       /* If this is the first time...  */
613       if (bsd_part_no == 0xFF)
614 	{
615 	  /* Check if the BSD label is within current PC slice.  */
616 	  if (*len < BSD_LABEL_SECTOR + 1)
617 	    {
618 	      errnum = ERR_BAD_PART_TABLE;
619 	      return 0;
620 	    }
621 
622 	  /* Read the BSD label.  */
623 	  if (! rawread (drive, *start + BSD_LABEL_SECTOR,
624 			 0, SECTOR_SIZE, buf))
625 	    return 0;
626 
627 	  /* Check if it is valid.  */
628 	  if (! BSD_LABEL_CHECK_MAG (buf))
629 	    {
630 	      errnum = ERR_BAD_PART_TABLE;
631 	      return 0;
632 	    }
633 
634 	  bsd_part_no = -1;
635 	}
636 
637       /* Search next valid BSD partition.  */
638       for (i = bsd_part_no + 1; i < BSD_LABEL_NPARTS (buf); i++)
639 	{
640 	  if (BSD_PART_TYPE (buf, i))
641 	    {
642 	      /* Note that *TYPE and *PARTITION were set
643 		 for current PC slice.  */
644 	      *type = (BSD_PART_TYPE (buf, i) << 8) | (*type & 0xFF);
645 	      *start = BSD_PART_START (buf, i);
646 	      *len = BSD_PART_LENGTH (buf, i);
647 	      *partition = (*partition & 0xFF00FF) | (i << 8);
648 
649 #ifndef STAGE1_5
650 	      /* XXX */
651 	      if ((drive & 0x80) && BSD_LABEL_DTYPE (buf) == DTYPE_SCSI)
652 		bsd_evil_hack = 4;
653 #endif /* ! STAGE1_5 */
654 
655 	      return 1;
656 	    }
657 	}
658 
659       errnum = ERR_NO_PART;
660       return 0;
661     }
662 
663   /* Get next Solaris partition in current PC slice.  */
664   int next_solaris_partition (void)
665     {
666       static unsigned long pcs_start;
667       int i;
668       int sol_part_no = (*partition & 0xFF00) >> 8;
669 
670       /* If this is the first time...  */
671       if (sol_part_no == 0xFF)
672 	{
673 	  /* Check if the Solaris label is within current PC slice.  */
674 	  if (*len < SOL_LABEL_LOC + 1)
675 	    {
676 	      errnum = ERR_BAD_PART_TABLE;
677 	      return 0;
678 	    }
679 
680 	  /* Read the Solaris label.  */
681 	  if (! rawread (drive, *start + SOL_LABEL_LOC, 0, SECTOR_SIZE, buf))
682 	    return 0;
683 
684 	  /* Check if it is valid.  */
685 	  if (! SOL_LABEL_CHECK_MAG (buf))
686 	    {
687 	      errnum = ERR_BAD_PART_TABLE;
688 	      return 0;
689 	    }
690 
691 	  sol_part_no = -1;
692 	  pcs_start = *start;	/* save the start of pc slice */
693 	}
694 
695       /* Search next valid Solaris partition.  */
696       for (i = sol_part_no + 1; i < SOL_LABEL_NPARTS; i++)
697 	{
698 	  if (SOL_PART_EXISTS (buf, i))
699 	    {
700 	      /* SOL_PART_START is relative to fdisk partition */
701 	      *start = SOL_PART_START (buf, i) + pcs_start;
702 	      *len = SOL_PART_LENGTH (buf, i);
703 	      *partition = (*partition & 0xFF00FF) | (i << 8);
704 
705 	      return 1;
706 	    }
707 	}
708 
709       errnum = ERR_NO_PART;
710       return 0;
711     }
712 
713   /* Get next PC slice. Be careful of that this function may return
714      an empty PC slice (i.e. a partition whose type is zero) as well.  */
715   int next_pc_slice (void)
716     {
717       int pc_slice_no = (*partition & 0xFF0000) >> 16;
718 
719       /* If this is the first time...  */
720       if (pc_slice_no == 0xFF)
721 	{
722 	  *offset = 0;
723 	  *ext_offset = 0;
724 	  *entry = -1;
725 	  pc_slice_no = -1;
726 	}
727 
728       /* Read the MBR or the boot sector of the extended partition.  */
729       if (! rawread (drive, *offset, 0, SECTOR_SIZE, buf))
730 	return 0;
731 
732       /* Check if it is valid.  */
733       if (! PC_MBR_CHECK_SIG (buf))
734 	{
735 	  errnum = ERR_BAD_PART_TABLE;
736 	  return 0;
737 	}
738 
739       /* Increase the entry number.  */
740       (*entry)++;
741 
742       /* If this is out of current partition table...  */
743       if (*entry == PC_SLICE_MAX)
744 	{
745 	  int i;
746 
747 	  /* Search the first extended partition in current table.  */
748 	  for (i = 0; i < PC_SLICE_MAX; i++)
749 	    {
750 	      if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (buf, i)))
751 		{
752 		  /* Found. Set the new offset and the entry number,
753 		     and restart this function.  */
754 		  *offset = *ext_offset + PC_SLICE_START (buf, i);
755 		  if (! *ext_offset)
756 		    *ext_offset = *offset;
757 		  *entry = -1;
758 		  return next_pc_slice ();
759 		}
760 	    }
761 
762 	  errnum = ERR_NO_PART;
763 	  return 0;
764 	}
765 
766       *type = PC_SLICE_TYPE (buf, *entry);
767       *start = *offset + PC_SLICE_START (buf, *entry);
768       *len = PC_SLICE_LENGTH (buf, *entry);
769 
770       /* The calculation of a PC slice number is complicated, because of
771 	 the rather odd definition of extended partitions. Even worse,
772 	 there is no guarantee that this is consistent with every
773 	 operating systems. Uggh.  */
774       if (pc_slice_no < PC_SLICE_MAX
775 	  || (! IS_PC_SLICE_TYPE_EXTENDED (*type)
776 	      && *type != PC_SLICE_TYPE_NONE))
777 	pc_slice_no++;
778 
779       *partition = (pc_slice_no << 16) | 0xFFFF;
780       return 1;
781     }
782 
783   /* Start the body of this function.  */
784 
785 #ifndef STAGE1_5
786   if (current_drive == NETWORK_DRIVE)
787     return 0;
788 #endif
789 
790   /* check for Solaris partition */
791   if (*partition != 0xFFFFFF && IS_PC_SLICE_TYPE_SOLARIS (*type & 0xff))
792     {
793       if (next_solaris_partition ())
794 	return 1;
795       errnum = ERR_NONE;
796     }
797 
798   /* If previous partition is a BSD partition or a PC slice which
799      contains BSD partitions...  */
800   if ((*partition != 0xFFFFFF && IS_PC_SLICE_TYPE_BSD (*type & 0xff))
801       || ! (drive & 0x80))
802     {
803       if (*type == PC_SLICE_TYPE_NONE)
804 	*type = PC_SLICE_TYPE_FREEBSD;
805 
806       /* Get next BSD partition, if any.  */
807       if (next_bsd_partition ())
808 	return 1;
809 
810       /* If the destination partition is a BSD partition and current
811 	 BSD partition has any error, abort the operation.  */
812       if ((dest & 0xFF00) != 0xFF00
813 	  && ((dest & 0xFF0000) == 0xFF0000
814 	      || (dest & 0xFF0000) == (*partition & 0xFF0000)))
815 	return 0;
816 
817       /* Ignore the error.  */
818       errnum = ERR_NONE;
819     }
820 
821   return next_pc_slice ();
822 }
823 
824 #ifndef STAGE1_5
825 static unsigned long cur_part_offset;
826 static unsigned long cur_part_addr;
827 #endif
828 
829 /* Open a partition.  */
830 int
831 real_open_partition (int flags)
832 {
833   unsigned long dest_partition = current_partition;
834   unsigned long part_offset;
835   unsigned long ext_offset;
836   int entry;
837   char buf[SECTOR_SIZE];
838   int unix_part, pc_slice;
839 
840   /* For simplicity.  */
841   auto int next (void);
842   int next (void)
843     {
844       int ret = next_partition (current_drive, dest_partition,
845 				&current_partition, &current_slice,
846 				&part_start, &part_length,
847 				&part_offset, &entry, &ext_offset, buf);
848       unix_part = (current_partition >> 8) & 0xFF;
849       pc_slice = current_partition >> 16;
850       return ret;
851     }
852 
853 #ifndef STAGE1_5
854   /* network drive */
855   if (current_drive == NETWORK_DRIVE)
856     return 1;
857 
858   if (! sane_partition ())
859     return 0;
860 #endif
861 
862   bsd_evil_hack = 0;
863   current_slice = 0;
864   part_start = 0;
865 
866   /* Make sure that buf_geom is valid. */
867   if (buf_drive != current_drive)
868     {
869       if (get_diskinfo (current_drive, &buf_geom))
870 	{
871 	  errnum = ERR_NO_DISK;
872 	  return 0;
873 	}
874       buf_drive = current_drive;
875       buf_track = BUF_CACHE_INVALID;
876     }
877   part_length =
878     (buf_geom.total_sectors > MAXUINT) ? MAXUINT : buf_geom.total_sectors;
879 
880   /* If this is the whole disk, return here.  */
881   if (! flags && current_partition == 0xFFFFFF)
882     return 1;
883 
884   if (flags)
885     dest_partition = 0xFFFFFF;
886 
887   /* Initialize CURRENT_PARTITION for next_partition.  */
888   current_partition = 0xFFFFFF;
889 
890   while (next ())
891     {
892 #ifndef STAGE1_5
893     loop_start:
894 
895       cur_part_offset = part_offset;
896       cur_part_addr = BOOT_PART_TABLE + (entry << 4);
897 #endif /* ! STAGE1_5 */
898 
899       /* If this is a valid partition...  */
900       if (current_slice)
901 	{
902 #ifndef STAGE1_5
903 	  /* Display partition information.  */
904 	  if (flags && ! IS_PC_SLICE_TYPE_EXTENDED (current_slice))
905 	    {
906 	      if (! do_completion)
907 		{
908 		  if (current_drive & 0x80)
909 		    grub_printf ("   Partition num: %d, ",
910 				 current_partition >> 16);
911 
912 		  if (! IS_PC_SLICE_TYPE_BSD (current_slice) &&
913 		      ! IS_PC_SLICE_TYPE_SOLARIS (current_slice))
914 		    check_and_print_mount ();
915 		  else
916 		    {
917 		      int got_part = 0;
918 		      int saved_slice = current_slice;
919 
920 		      while (next ())
921 			{
922 			  if (unix_part == 0xFF)
923 			    break;
924 
925 			  if (! got_part)
926 			    {
927 			      grub_printf ("[BSD/SOLARIS sub-partitions immediately follow]\n");
928 			      got_part = 1;
929 			    }
930 
931 			  grub_printf ("     BSD/SOLARIS Partition num: \'%c\', ",
932 				       unix_part + 'a');
933 			  check_and_print_mount ();
934 			}
935 
936 		      if (! got_part)
937 			grub_printf (" No BSD/SOLARIS sub-partition found, partition type 0x%x\n",
938 				     saved_slice);
939 
940 		      if (errnum)
941 			{
942 			  errnum = ERR_NONE;
943 			  break;
944 			}
945 
946 		      goto loop_start;
947 		    }
948 		}
949 	      else
950 		{
951 		  if (unix_part != 0xFF)
952 		    {
953 		      char str[16];
954 
955 		      if (! (current_drive & 0x80)
956 			  || (dest_partition >> 16) == pc_slice)
957 			grub_sprintf (str, "%c)", unix_part + 'a');
958 		      else
959 			grub_sprintf (str, "%d,%c)",
960 				      pc_slice, unix_part + 'a');
961 		      print_a_completion (str);
962 		    }
963 		  else if (! IS_PC_SLICE_TYPE_BSD (current_slice) &&
964 		      ! IS_PC_SLICE_TYPE_SOLARIS (current_slice))
965 		    {
966 		      char str[8];
967 
968 		      grub_sprintf (str, "%d)", pc_slice);
969 		      print_a_completion (str);
970 		    }
971 		}
972 	    }
973 
974 	  errnum = ERR_NONE;
975 #endif /* ! STAGE1_5 */
976 
977 	  /* Check if this is the destination partition.  */
978 	  if (! flags
979 	      && (dest_partition == current_partition
980 		  || ((dest_partition >> 16) == 0xFF
981 		      && ((dest_partition >> 8) & 0xFF) == unix_part)))
982 	    return 1;
983 	}
984     }
985 
986 #ifndef STAGE1_5
987   if (flags)
988     {
989       if (! (current_drive & 0x80))
990 	{
991 	  current_partition = 0xFFFFFF;
992 	  check_and_print_mount ();
993 	}
994 
995       errnum = ERR_NONE;
996       return 1;
997     }
998 #endif /* ! STAGE1_5 */
999 
1000   return 0;
1001 }
1002 
1003 
1004 int
1005 open_partition (void)
1006 {
1007   return real_open_partition (0);
1008 }
1009 
1010 
1011 #ifndef STAGE1_5
1012 /* XX used for device completion in 'set_device' and 'print_completions' */
1013 static int incomplete, disk_choice;
1014 static enum
1015 {
1016   PART_UNSPECIFIED = 0,
1017   PART_DISK,
1018   PART_CHOSEN,
1019 }
1020 part_choice;
1021 #endif /* ! STAGE1_5 */
1022 
1023 char *
1024 set_device (char *device)
1025 {
1026 #ifdef STAGE1_5
1027     /* In Stage 1.5, the first 4 bytes of FILENAME has a device number.  */
1028   unsigned long dev = *((unsigned long *) device);
1029   int drive = (dev >> 24) & 0xFF;
1030   int partition = dev & 0xFFFFFF;
1031 
1032   /* If DRIVE is disabled, use SAVED_DRIVE instead.  */
1033   if (drive == GRUB_INVALID_DRIVE)
1034     current_drive = saved_drive;
1035   else
1036     current_drive = drive;
1037 
1038   /* The `partition' part must always have a valid number.  */
1039   current_partition = partition;
1040 
1041   return device + sizeof (unsigned long);
1042 
1043 #else /* ! STAGE1_5 */
1044 
1045   int result = 0;
1046 
1047   incomplete = 0;
1048   disk_choice = 1;
1049   part_choice = PART_UNSPECIFIED;
1050   current_drive = saved_drive;
1051   current_partition = 0xFFFFFF;
1052 
1053   if (*device == '(' && !*(device + 1))
1054     /* user has given '(' only, let disk_choice handle what disks we have */
1055     return device + 1;
1056 
1057   if (*device == '(' && *(++device))
1058     {
1059       if (*device != ',' && *device != ')')
1060 	{
1061 	  char ch = *device;
1062 #ifdef SUPPORT_NETBOOT
1063 	  if (*device == 'f' || *device == 'h'
1064 	      || (*device == 'n' && network_ready)
1065 	      || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE))
1066 #else
1067 	  if (*device == 'f' || *device == 'h'
1068 	      || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE))
1069 #endif /* SUPPORT_NETBOOT */
1070 	    {
1071 	      /* user has given '([fhn]', check for resp. add 'd' and
1072 		 let disk_choice handle what disks we have */
1073 	      if (!*(device + 1))
1074 		{
1075 		  device++;
1076 		  *device++ = 'd';
1077 		  *device = '\0';
1078 		  return device;
1079 		}
1080 	      else if (*(device + 1) == 'd' && !*(device + 2))
1081 		return device + 2;
1082 	    }
1083 
1084 	  if ((*device == 'f'
1085 	       || *device == 'h'
1086 #ifdef SUPPORT_NETBOOT
1087 	       || (*device == 'n' && network_ready)
1088 #endif
1089 	       || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE))
1090 	      && (device += 2, (*(device - 1) != 'd')))
1091 	    errnum = ERR_NUMBER_PARSING;
1092 
1093 #ifdef SUPPORT_NETBOOT
1094 	  if (ch == 'n' && network_ready)
1095 	    current_drive = NETWORK_DRIVE;
1096 	  else
1097 #endif /* SUPPORT_NETBOOT */
1098 	    {
1099 	      if (ch == 'c' && cdrom_drive != GRUB_INVALID_DRIVE)
1100 		current_drive = cdrom_drive;
1101 	      else
1102 		{
1103 		  safe_parse_maxint (&device, (int *) &current_drive);
1104 
1105 		  disk_choice = 0;
1106 		  if (ch == 'h')
1107 		    current_drive += 0x80;
1108 		}
1109 	    }
1110 	}
1111 
1112       if (errnum)
1113 	return 0;
1114 
1115       if (*device == ')')
1116 	{
1117 	  part_choice = PART_CHOSEN;
1118 	  result = 1;
1119 	}
1120       else if (*device == ',')
1121 	{
1122 	  /* Either an absolute PC, BSD, or Solaris partition. */
1123 	  disk_choice = 0;
1124 	  part_choice ++;
1125 	  device++;
1126 
1127 	  if (*device >= '0' && *device <= '9')
1128 	    {
1129 	      part_choice ++;
1130 	      current_partition = 0;
1131 
1132 	      if (!(current_drive & 0x80)
1133 		  || !safe_parse_maxint (&device, (int *) &current_partition)
1134 		  || current_partition > 254)
1135 		{
1136 		  errnum = ERR_DEV_FORMAT;
1137 		  return 0;
1138 		}
1139 
1140 	      current_partition = (current_partition << 16) + 0xFFFF;
1141 
1142 	      if (*device == ',')
1143 		device++;
1144 
1145 	      if (*device >= 'a' && *device <= 'p')
1146 		{
1147 		  current_partition = (((*(device++) - 'a') << 8)
1148 				       | (current_partition & 0xFF00FF));
1149 		}
1150 	    }
1151 	  else if (*device >= 'a' && *device <= 'p')
1152 	    {
1153 	      part_choice ++;
1154 	      current_partition = ((*(device++) - 'a') << 8) | 0xFF00FF;
1155 	    }
1156 
1157 	  if (*device == ')')
1158 	    {
1159 	      if (part_choice == PART_DISK)
1160 		{
1161 		  current_partition = saved_partition;
1162 		  part_choice ++;
1163 		}
1164 
1165 	      result = 1;
1166 	    }
1167 	}
1168     }
1169 
1170   if (! sane_partition ())
1171     return 0;
1172 
1173   if (result)
1174     return device + 1;
1175   else
1176     {
1177       if (!*device)
1178 	incomplete = 1;
1179       errnum = ERR_DEV_FORMAT;
1180     }
1181 
1182   return 0;
1183 
1184 #endif /* ! STAGE1_5 */
1185 }
1186 
1187 /*
1188  *  This performs a "mount" on the current device, both drive and partition
1189  *  number.
1190  */
1191 
1192 int
1193 open_device (void)
1194 {
1195   if (open_partition ())
1196     attempt_mount ();
1197 
1198   if (errnum != ERR_NONE)
1199     return 0;
1200 
1201   return 1;
1202 }
1203 
1204 
1205 #ifndef STAGE1_5
1206 int
1207 set_bootdev (int hdbias)
1208 {
1209   int i, j;
1210 
1211   /* Copy the boot partition information to 0x7be-0x7fd for chain-loading.  */
1212   if ((saved_drive & 0x80) && cur_part_addr)
1213     {
1214       if (rawread (saved_drive, cur_part_offset,
1215 		   0, SECTOR_SIZE, (char *) SCRATCHADDR))
1216 	{
1217 	  char *dst, *src;
1218 
1219 	  /* Need only the partition table.
1220 	     XXX: We cannot use grub_memmove because BOOT_PART_TABLE
1221 	     (0x07be) is less than 0x1000.  */
1222 	  dst = (char *) BOOT_PART_TABLE;
1223 	  src = (char *) SCRATCHADDR + BOOTSEC_PART_OFFSET;
1224 	  while (dst < (char *) BOOT_PART_TABLE + BOOTSEC_PART_LENGTH)
1225 	    *dst++ = *src++;
1226 
1227 	  /* Set the active flag of the booted partition.  */
1228 	  for (i = 0; i < 4; i++)
1229 	    PC_SLICE_FLAG (BOOT_PART_TABLE, i) = 0;
1230 
1231 	  *((unsigned char *) cur_part_addr) = PC_SLICE_FLAG_BOOTABLE;
1232 	  boot_part_addr = cur_part_addr;
1233 	}
1234       else
1235 	return 0;
1236     }
1237 
1238   /*
1239    *  Set BSD boot device.
1240    */
1241   i = (saved_partition >> 16) + 2;
1242   if (saved_partition == 0xFFFFFF)
1243     i = 1;
1244   else if ((saved_partition >> 16) == 0xFF)
1245     i = 0;
1246 
1247   /* FIXME: extremely evil hack!!! */
1248   j = 2;
1249   if (saved_drive & 0x80)
1250     j = bsd_evil_hack;
1251 
1252   return MAKEBOOTDEV (j, (i >> 4), (i & 0xF),
1253 		      ((saved_drive - hdbias) & 0x7F),
1254 		      ((saved_partition >> 8) & 0xFF));
1255 }
1256 #endif /* STAGE1_5 */
1257 
1258 
1259 static char *
1260 setup_part (char *filename)
1261 {
1262 #ifdef STAGE1_5
1263 
1264   if (! (filename = set_device (filename)))
1265     {
1266       current_drive = GRUB_INVALID_DRIVE;
1267       return 0;
1268     }
1269 
1270 # ifndef NO_BLOCK_FILES
1271   if (*filename != '/')
1272     open_partition ();
1273   else
1274 # endif /* ! NO_BLOCK_FILES */
1275     open_device ();
1276 
1277 #else /* ! STAGE1_5 */
1278 
1279   if (*filename == '(')
1280     {
1281       if ((filename = set_device (filename)) == 0)
1282 	{
1283 	  current_drive = GRUB_INVALID_DRIVE;
1284 	  return 0;
1285 	}
1286 # ifndef NO_BLOCK_FILES
1287       if (*filename != '/' && current_drive != NETWORK_DRIVE)
1288 	open_partition ();
1289       else
1290 # endif /* ! NO_BLOCK_FILES */
1291 	open_device ();
1292     }
1293   else if (saved_drive != current_drive
1294 	   || saved_partition != current_partition
1295 	   || (*filename == '/' && fsys_type == NUM_FSYS)
1296 	   || buf_drive == -1)
1297     {
1298       current_drive = saved_drive;
1299       current_partition = saved_partition;
1300       /* allow for the error case of "no filesystem" after the partition
1301          is found.  This makes block files work fine on no filesystem */
1302 # ifndef NO_BLOCK_FILES
1303       if (*filename != '/' && current_drive != NETWORK_DRIVE)
1304 	open_partition ();
1305       else
1306 # endif /* ! NO_BLOCK_FILES */
1307 	open_device ();
1308     }
1309 
1310 #endif /* ! STAGE1_5 */
1311 
1312   if (errnum && (*filename == '/' || errnum != ERR_FSYS_MOUNT))
1313     return 0;
1314   else
1315     errnum = 0;
1316 
1317 #ifndef STAGE1_5
1318   if (!sane_partition ())
1319     return 0;
1320 #endif
1321 
1322   return filename;
1323 }
1324 
1325 
1326 #ifndef STAGE1_5
1327 /*
1328  *  This prints the filesystem type or gives relevant information.
1329  */
1330 
1331 void
1332 print_fsys_type (void)
1333 {
1334   if (! do_completion)
1335     {
1336       grub_printf (" Filesystem type ");
1337 
1338       if (fsys_type != NUM_FSYS)
1339 	grub_printf ("is %s, ", fsys_table[fsys_type].name);
1340       else
1341 	grub_printf ("unknown, ");
1342 
1343       if (current_partition == 0xFFFFFF)
1344 	grub_printf ("using whole disk\n");
1345       else
1346 	grub_printf ("partition type 0x%x\n", current_slice & 0xFF);
1347     }
1348 }
1349 #endif /* STAGE1_5 */
1350 
1351 #ifndef STAGE1_5
1352 /* If DO_COMPLETION is true, just print NAME. Otherwise save the unique
1353    part into UNIQUE_STRING.  */
1354 void
1355 print_a_completion (char *name)
1356 {
1357   /* If NAME is "." or "..", do not count it.  */
1358   if (grub_strcmp (name, ".") == 0 || grub_strcmp (name, "..") == 0)
1359     return;
1360 
1361   if (do_completion)
1362     {
1363       char *buf = unique_string;
1364 
1365       if (! unique)
1366 	while ((*buf++ = *name++))
1367 	  ;
1368       else
1369 	{
1370 	  while (*buf && (*buf == *name))
1371 	    {
1372 	      buf++;
1373 	      name++;
1374 	    }
1375 	  /* mismatch, strip it.  */
1376 	  *buf = '\0';
1377 	}
1378     }
1379   else
1380     grub_printf (" %s", name);
1381 
1382   unique++;
1383 }
1384 
1385 /*
1386  *  This lists the possible completions of a device string, filename, or
1387  *  any sane combination of the two.
1388  */
1389 
1390 int
1391 print_completions (int is_filename, int is_completion)
1392 {
1393   char *buf = (char *) COMPLETION_BUF;
1394   char *ptr = buf;
1395 
1396   unique_string = (char *) UNIQUE_BUF;
1397   *unique_string = 0;
1398   unique = 0;
1399   do_completion = is_completion;
1400 
1401   if (! is_filename)
1402     {
1403       /* Print the completions of builtin commands.  */
1404       struct builtin **builtin;
1405 
1406       if (! is_completion)
1407 	grub_printf (" Possible commands are:");
1408 
1409       for (builtin = builtin_table; (*builtin); builtin++)
1410 	{
1411 	  /* If *BUILTIN cannot be run in the command-line, skip it.  */
1412 	  if (! ((*builtin)->flags & BUILTIN_CMDLINE))
1413 	    continue;
1414 
1415 	  if (substring (buf, (*builtin)->name) <= 0)
1416 	    print_a_completion ((*builtin)->name);
1417 	}
1418 
1419       if (is_completion && *unique_string)
1420 	{
1421 	  if (unique == 1)
1422 	    {
1423 	      char *u = unique_string + grub_strlen (unique_string);
1424 
1425 	      *u++ = ' ';
1426 	      *u = 0;
1427 	    }
1428 
1429 	  grub_strcpy (buf, unique_string);
1430 	}
1431 
1432       if (! is_completion)
1433 	grub_putchar ('\n');
1434 
1435       print_error ();
1436       do_completion = 0;
1437       if (errnum)
1438 	return -1;
1439       else
1440 	return unique - 1;
1441     }
1442 
1443   if (*buf == '/' || (ptr = set_device (buf)) || incomplete)
1444     {
1445       errnum = 0;
1446 
1447       if (*buf == '(' && (incomplete || ! *ptr))
1448 	{
1449 	  if (! part_choice)
1450 	    {
1451 	      /* disk completions */
1452 	      int disk_no, i, j;
1453 	      struct geometry geom;
1454 
1455 	      if (! is_completion)
1456 		grub_printf (" Possible disks are: ");
1457 
1458 	      if (!ptr
1459 		  || *(ptr-1) != 'd'
1460 #ifdef SUPPORT_NETBOOT
1461 		  || *(ptr-2) != 'n'
1462 #endif /* SUPPORT_NETBOOT */
1463 		  || *(ptr-2) != 'c')
1464 		{
1465 		  for (i = (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'h') ? 1:0);
1466 		       i < (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'f') ? 1:2);
1467 		       i++)
1468 		    {
1469 		      for (j = 0; j < 8; j++)
1470 			{
1471 			  disk_no = (i * 0x80) + j;
1472 			  if ((disk_choice || disk_no == current_drive)
1473 			      && ! get_diskinfo (disk_no, &geom))
1474 			    {
1475 			      char dev_name[8];
1476 
1477 			      grub_sprintf (dev_name, "%cd%d", i ? 'h':'f', j);
1478 			      print_a_completion (dev_name);
1479 			    }
1480 			}
1481 		    }
1482 		}
1483 
1484 	      if (cdrom_drive != GRUB_INVALID_DRIVE
1485 		  && (disk_choice || cdrom_drive == current_drive)
1486 		  && (!ptr
1487 		      || *(ptr-1) == '('
1488 		      || (*(ptr-1) == 'd' && *(ptr-2) == 'c')))
1489 		print_a_completion ("cd");
1490 
1491 # ifdef SUPPORT_NETBOOT
1492 	      if (network_ready
1493 		  && (disk_choice || NETWORK_DRIVE == current_drive)
1494 		  && (!ptr
1495 		      || *(ptr-1) == '('
1496 		      || (*(ptr-1) == 'd' && *(ptr-2) == 'n')))
1497 		print_a_completion ("nd");
1498 # endif /* SUPPORT_NETBOOT */
1499 
1500 	      if (is_completion && *unique_string)
1501 		{
1502 		  ptr = buf;
1503 		  while (*ptr != '(')
1504 		    ptr--;
1505 		  ptr++;
1506 		  grub_strcpy (ptr, unique_string);
1507 		  if (unique == 1)
1508 		    {
1509 		      ptr += grub_strlen (ptr);
1510 		      if (*unique_string == 'h')
1511 			{
1512 			  *ptr++ = ',';
1513 			  *ptr = 0;
1514 			}
1515 		      else
1516 			{
1517 			  *ptr++ = ')';
1518 			  *ptr = 0;
1519 			}
1520 		    }
1521 		}
1522 
1523 	      if (! is_completion)
1524 		grub_putchar ('\n');
1525 	    }
1526 	  else
1527 	    {
1528 	      /* partition completions */
1529 	      if (part_choice == PART_CHOSEN
1530 		  && open_partition ()
1531 		  && ! IS_PC_SLICE_TYPE_BSD (current_slice))
1532 		{
1533 		  unique = 1;
1534 		  ptr = buf + grub_strlen (buf);
1535 		  if (*(ptr - 1) != ')')
1536 		    {
1537 		      *ptr++ = ')';
1538 		      *ptr = 0;
1539 		    }
1540 		}
1541 	      else
1542 		{
1543 		  if (! is_completion)
1544 		    grub_printf (" Possible partitions are:\n");
1545 		  real_open_partition (1);
1546 
1547 		  if (is_completion && *unique_string)
1548 		    {
1549 		      ptr = buf;
1550 		      while (*ptr++ != ',')
1551 			;
1552 		      grub_strcpy (ptr, unique_string);
1553 		    }
1554 		}
1555 	    }
1556 	}
1557       else if (ptr && *ptr == '/')
1558 	{
1559 	  /* filename completions */
1560 	  if (! is_completion)
1561 	    grub_printf (" Possible files are:");
1562 
1563 	  dir (buf);
1564 
1565 	  if (is_completion && *unique_string)
1566 	    {
1567 	      ptr += grub_strlen (ptr);
1568 	      while (*ptr != '/')
1569 		ptr--;
1570 	      ptr++;
1571 
1572 	      grub_strcpy (ptr, unique_string);
1573 
1574 	      if (unique == 1)
1575 		{
1576 		  ptr += grub_strlen (unique_string);
1577 
1578 		  /* Check if the file UNIQUE_STRING is a directory.  */
1579 		  *ptr = '/';
1580 		  *(ptr + 1) = 0;
1581 
1582 		  dir (buf);
1583 
1584 		  /* Restore the original unique value.  */
1585 		  unique = 1;
1586 
1587 		  if (errnum)
1588 		    {
1589 		      /* Regular file */
1590 		      errnum = 0;
1591 		      *ptr = ' ';
1592 		      *(ptr + 1) = 0;
1593 		    }
1594 		}
1595 	    }
1596 
1597 	  if (! is_completion)
1598 	    grub_putchar ('\n');
1599 	}
1600       else
1601 	errnum = ERR_BAD_FILENAME;
1602     }
1603 
1604   print_error ();
1605   do_completion = 0;
1606   if (errnum)
1607     return -1;
1608   else
1609     return unique - 1;
1610 }
1611 #endif /* STAGE1_5 */
1612 
1613 
1614 /*
1615  *  This is the generic file open function.
1616  */
1617 
1618 int
1619 grub_open (char *filename)
1620 {
1621 #ifndef NO_DECOMPRESSION
1622   compressed_file = 0;
1623 #endif /* NO_DECOMPRESSION */
1624 
1625   /* if any "dir" function uses/sets filepos, it must
1626      set it to zero before returning if opening a file! */
1627   filepos = 0;
1628 
1629   if (!(filename = setup_part (filename)))
1630     return 0;
1631 
1632 #ifndef NO_BLOCK_FILES
1633   block_file = 0;
1634 #endif /* NO_BLOCK_FILES */
1635 
1636   /* This accounts for partial filesystem implementations. */
1637   fsmax = MAXINT;
1638 
1639   if (*filename != '/' && current_drive != NETWORK_DRIVE)
1640     {
1641 #ifndef NO_BLOCK_FILES
1642       char *ptr = filename;
1643       int tmp, list_addr = BLK_BLKLIST_START;
1644       filemax = 0;
1645 
1646       while (list_addr < BLK_MAX_ADDR)
1647 	{
1648 	  tmp = 0;
1649 	  safe_parse_maxint (&ptr, &tmp);
1650 	  errnum = 0;
1651 
1652 	  if (*ptr != '+')
1653 	    {
1654 	      if ((*ptr && *ptr != '/' && !isspace (*ptr))
1655 		  || tmp == 0 || tmp > filemax)
1656 		errnum = ERR_BAD_FILENAME;
1657 	      else
1658 		filemax = tmp;
1659 
1660 	      break;
1661 	    }
1662 
1663 	  /* since we use the same filesystem buffer, mark it to
1664 	     be remounted */
1665 	  fsys_type = NUM_FSYS;
1666 
1667 	  BLK_BLKSTART (list_addr) = tmp;
1668 	  ptr++;
1669 
1670 	  if (!safe_parse_maxint (&ptr, &tmp)
1671 	      || tmp == 0
1672 	      || (*ptr && *ptr != ',' && *ptr != '/' && !isspace (*ptr)))
1673 	    {
1674 	      errnum = ERR_BAD_FILENAME;
1675 	      break;
1676 	    }
1677 
1678 	  BLK_BLKLENGTH (list_addr) = tmp;
1679 
1680 	  filemax += (tmp * SECTOR_SIZE);
1681 	  list_addr += BLK_BLKLIST_INC_VAL;
1682 
1683 	  if (*ptr != ',')
1684 	    break;
1685 
1686 	  ptr++;
1687 	}
1688 
1689       if (list_addr < BLK_MAX_ADDR && ptr != filename && !errnum)
1690 	{
1691 	  block_file = 1;
1692 	  BLK_CUR_FILEPOS = 0;
1693 	  BLK_CUR_BLKLIST = BLK_BLKLIST_START;
1694 	  BLK_CUR_BLKNUM = 0;
1695 
1696 #ifndef NO_DECOMPRESSION
1697 	  return gunzip_test_header ();
1698 #else /* NO_DECOMPRESSION */
1699 	  return 1;
1700 #endif /* NO_DECOMPRESSION */
1701 	}
1702 #else /* NO_BLOCK_FILES */
1703       errnum = ERR_BAD_FILENAME;
1704 #endif /* NO_BLOCK_FILES */
1705     }
1706 
1707   if (!errnum && fsys_type == NUM_FSYS)
1708     errnum = ERR_FSYS_MOUNT;
1709 
1710 # ifndef STAGE1_5
1711   /* set "dir" function to open a file */
1712   print_possibilities = 0;
1713 # endif
1714 
1715   if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename))
1716     {
1717 #ifndef NO_DECOMPRESSION
1718       return gunzip_test_header ();
1719 #else /* NO_DECOMPRESSION */
1720       return 1;
1721 #endif /* NO_DECOMPRESSION */
1722     }
1723 
1724   return 0;
1725 }
1726 
1727 
1728 int
1729 grub_read (char *buf, int len)
1730 {
1731   /* Make sure "filepos" is a sane value */
1732   if ((filepos < 0) || (filepos > filemax))
1733     filepos = filemax;
1734 
1735   /* Make sure "len" is a sane value */
1736   if ((len < 0) || (len > (filemax - filepos)))
1737     len = filemax - filepos;
1738 
1739   /* if target file position is past the end of
1740      the supported/configured filesize, then
1741      there is an error */
1742   if (filepos + len > fsmax)
1743     {
1744       errnum = ERR_FILELENGTH;
1745       return 0;
1746     }
1747 
1748 #ifndef NO_DECOMPRESSION
1749   if (compressed_file)
1750     return gunzip_read (buf, len);
1751 #endif /* NO_DECOMPRESSION */
1752 
1753 #ifndef NO_BLOCK_FILES
1754   if (block_file)
1755     {
1756       int size, off, ret = 0;
1757 
1758       while (len && !errnum)
1759 	{
1760 	  /* we may need to look for the right block in the list(s) */
1761 	  if (filepos < BLK_CUR_FILEPOS)
1762 	    {
1763 	      BLK_CUR_FILEPOS = 0;
1764 	      BLK_CUR_BLKLIST = BLK_BLKLIST_START;
1765 	      BLK_CUR_BLKNUM = 0;
1766 	    }
1767 
1768 	  /* run BLK_CUR_FILEPOS up to filepos */
1769 	  while (filepos > BLK_CUR_FILEPOS)
1770 	    {
1771 	      if ((filepos - (BLK_CUR_FILEPOS & ~(SECTOR_SIZE - 1)))
1772 		  >= SECTOR_SIZE)
1773 		{
1774 		  BLK_CUR_FILEPOS += SECTOR_SIZE;
1775 		  BLK_CUR_BLKNUM++;
1776 
1777 		  if (BLK_CUR_BLKNUM >= BLK_BLKLENGTH (BLK_CUR_BLKLIST))
1778 		    {
1779 		      BLK_CUR_BLKLIST += BLK_BLKLIST_INC_VAL;
1780 		      BLK_CUR_BLKNUM = 0;
1781 		    }
1782 		}
1783 	      else
1784 		BLK_CUR_FILEPOS = filepos;
1785 	    }
1786 
1787 	  off = filepos & (SECTOR_SIZE - 1);
1788 	  size = ((BLK_BLKLENGTH (BLK_CUR_BLKLIST) - BLK_CUR_BLKNUM)
1789 		  * SECTOR_SIZE) - off;
1790 	  if (size > len)
1791 	    size = len;
1792 
1793 	  disk_read_func = disk_read_hook;
1794 
1795 	  /* read current block and put it in the right place in memory */
1796 	  devread (BLK_BLKSTART (BLK_CUR_BLKLIST) + BLK_CUR_BLKNUM,
1797 		   off, size, buf);
1798 
1799 	  disk_read_func = NULL;
1800 
1801 	  len -= size;
1802 	  filepos += size;
1803 	  ret += size;
1804 	  buf += size;
1805 	}
1806 
1807       if (errnum)
1808 	ret = 0;
1809 
1810       return ret;
1811     }
1812 #endif /* NO_BLOCK_FILES */
1813 
1814   if (fsys_type == NUM_FSYS)
1815     {
1816       errnum = ERR_FSYS_MOUNT;
1817       return 0;
1818     }
1819 
1820   return (*(fsys_table[fsys_type].read_func)) (buf, len);
1821 }
1822 
1823 #ifndef STAGE1_5
1824 /* Reposition a file offset.  */
1825 int
1826 grub_seek (int offset)
1827 {
1828   if (offset > filemax || offset < 0)
1829     return -1;
1830 
1831   filepos = offset;
1832   return offset;
1833 }
1834 
1835 int
1836 dir (char *dirname)
1837 {
1838 #ifndef NO_DECOMPRESSION
1839   compressed_file = 0;
1840 #endif /* NO_DECOMPRESSION */
1841 
1842   if (!(dirname = setup_part (dirname)))
1843     return 0;
1844 
1845   if (*dirname != '/')
1846     errnum = ERR_BAD_FILENAME;
1847 
1848   if (fsys_type == NUM_FSYS)
1849     errnum = ERR_FSYS_MOUNT;
1850 
1851   if (errnum)
1852     return 0;
1853 
1854   /* set "dir" function to list completions */
1855   print_possibilities = 1;
1856 
1857   return (*(fsys_table[fsys_type].dir_func)) (dirname);
1858 }
1859 #endif /* STAGE1_5 */
1860 
1861 void
1862 grub_close (void)
1863 {
1864 #ifndef NO_BLOCK_FILES
1865   if (block_file)
1866     return;
1867 #endif /* NO_BLOCK_FILES */
1868 
1869   if (fsys_table[fsys_type].close_func != 0)
1870     (*(fsys_table[fsys_type].close_func)) ();
1871 }
1872