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