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