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