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