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