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 */
35void (*disk_read_hook) (unsigned long long, int, int) = NULL;
36void (*disk_read_func) (unsigned long long, int, int) = NULL;
37
38#ifndef STAGE1_5
39int print_possibilities;
40
41static int do_completion;
42static int unique;
43static char *unique_string;
44
45#endif
46
47int fsmax;
48struct 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. */
98unsigned long current_drive = GRUB_INVALID_DRIVE;
99unsigned 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.  */
104unsigned 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"
113int bsd_evil_hack;
114
115/* filesystem type */
116int fsys_type = NUM_FSYS;
117#ifndef NO_BLOCK_FILES
118static int block_file = 0;
119#endif /* NO_BLOCK_FILES */
120
121/* these are the translated numbers for the open partition */
122unsigned long long part_start;
123unsigned long long part_length;
124
125int current_slice;
126
127/* ZFS root filesystem for booting */
128char current_rootpool[MAXNAMELEN];
129char current_bootfs[MAXNAMELEN];
130uint64_t current_bootfs_obj;
131char current_bootpath[MAXPATHLEN];
132char current_devid[MAXPATHLEN];
133int is_zfs_mount;
134unsigned long best_drive;
135unsigned long best_part;
136int find_best_root;
137
138/* disk buffer parameters */
139int buf_drive = -1;
140unsigned long long buf_track;
141struct geometry buf_geom;
142
143/* filesystem common variables */
144int filepos;
145int filemax;
146
147static inline unsigned long
148grub_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
157int
158rawread(int drive, unsigned long long 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 long long 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 long long 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 long long 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
307int
308devread(unsigned long long 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 ("<%llu, %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
345int
346rawwrite(int drive, unsigned long long 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
378int
379devwrite(unsigned long long 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
408static int
409sane_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
430static void
431attempt_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.  */
455int
456make_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.  */
514int
515set_partition_hidden_flag (int hidden)
516{
517  unsigned long part = 0xFFFFFF;
518  unsigned long 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
571static void
572check_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.  */
595int
596next_partition (unsigned long drive, unsigned long dest,
597		unsigned long *partition, int *type,
598		unsigned long long *start, unsigned long long *len,
599		unsigned long long *offset, int *entry,
600                unsigned long long *ext_offset,
601                unsigned long 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
903static unsigned long cur_part_offset;
904static unsigned long cur_part_addr;
905#endif
906
907/* Open a partition.  */
908int
909real_open_partition (int flags)
910{
911  unsigned long dest_partition = current_partition;
912  unsigned long long part_offset;
913  unsigned long long ext_offset;
914  unsigned long 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
1086int
1087open_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' */
1095static int incomplete, disk_choice;
1096static enum
1097{
1098  PART_UNSPECIFIED = 0,
1099  PART_DISK,
1100  PART_CHOSEN,
1101}
1102part_choice;
1103#endif /* ! STAGE1_5 */
1104
1105char *
1106set_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
1274int
1275open_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
1288int
1289set_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
1341static char *
1342setup_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
1413void
1414print_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.  */
1436void
1437print_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
1472int
1473print_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
1700int
1701grub_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
1810int
1811grub_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.  */
1907int
1908grub_seek (int offset)
1909{
1910  if (offset > filemax || offset < 0)
1911    return -1;
1912
1913  filepos = offset;
1914  return offset;
1915}
1916
1917int
1918dir (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
1943void
1944grub_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