1 /* disk_io.c - implement abstract BIOS disk input and output */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
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.
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.
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.
26 #ifdef SUPPORT_NETBOOT
34 /* instrumentation variables */
35 void (*disk_read_hook
) (unsigned long long, int, int) = NULL
;
36 void (*disk_read_func
) (unsigned long long, int, int) = NULL
;
39 int print_possibilities
;
41 static int do_completion
;
43 static char *unique_string
;
48 struct fsys_entry fsys_table
[NUM_FSYS
+ 1] =
50 /* TFTP should come first because others don't handle net device. */
52 {"tftp", tftp_mount
, tftp_read
, tftp_dir
, tftp_close
, 0},
55 {"fat", fat_mount
, fat_read
, fat_dir
, 0, 0},
58 {"ext2fs", ext2fs_mount
, ext2fs_read
, ext2fs_dir
, 0, 0},
61 {"minix", minix_mount
, minix_read
, minix_dir
, 0, 0},
64 {"reiserfs", reiserfs_mount
, reiserfs_read
, reiserfs_dir
, 0, reiserfs_embed
},
67 {"vstafs", vstafs_mount
, vstafs_read
, vstafs_dir
, 0, 0},
70 {"jfs", jfs_mount
, jfs_read
, jfs_dir
, 0, jfs_embed
},
73 {"xfs", xfs_mount
, xfs_read
, xfs_dir
, 0, 0},
76 {"ufs", ufs_mount
, ufs_read
, ufs_dir
, 0, ufs_embed
},
79 {"ufs2", ufs2_mount
, ufs2_read
, ufs2_dir
, 0, ufs2_embed
},
82 {"zfs", zfs_mount
, zfs_read
, zfs_open
, 0, zfs_embed
},
85 {"iso9660", iso9660_mount
, iso9660_read
, iso9660_dir
, 0, 0},
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. */
90 {"ffs", ffs_mount
, ffs_read
, ffs_dir
, 0, ffs_embed
},
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
;
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;
108 * Global variables describing details of the filesystem
111 /* FIXME: BSD evil hack */
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 */
121 /* these are the translated numbers for the open partition */
122 unsigned long long part_start
;
123 unsigned long long part_length
;
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
];
134 unsigned long best_drive
;
135 unsigned long best_part
;
138 /* disk buffer parameters */
140 unsigned long long buf_track
;
141 struct geometry buf_geom
;
143 /* filesystem common variables */
147 static inline unsigned long
148 grub_log2 (unsigned long word
)
150 asm volatile ("bsfl %1,%0"
155 #define log2 grub_log2
158 rawread(int drive
, unsigned long long sector
, int byte_offset
, int byte_len
,
161 int slen
, sectors_per_vtrack
;
162 int sector_size_bits
= log2 (buf_geom
.sector_size
);
167 while (byte_len
> 0 && !errnum
)
169 int soff
, num_sect
, size
= byte_len
;
170 unsigned long long track
;
174 * Check track buffer. If it isn't valid or it is from the
175 * wrong disk, then reset the disk geometry.
177 if (buf_drive
!= drive
)
179 if (get_diskinfo (drive
, &buf_geom
))
181 errnum
= ERR_NO_DISK
;
185 buf_track
= BUF_CACHE_INVALID
;
186 sector_size_bits
= log2 (buf_geom
.sector_size
);
189 slen
= ((byte_offset
+ byte_len
+ buf_geom
.sector_size
- 1)
190 >> sector_size_bits
);
192 /* Eliminate a buffer overflow. */
193 if ((buf_geom
.sectors
<< sector_size_bits
) > BUFFERLEN
)
194 sectors_per_vtrack
= (BUFFERLEN
>> sector_size_bits
);
196 sectors_per_vtrack
= buf_geom
.sectors
;
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
);
205 if (track
!= buf_track
)
207 int bios_err
, read_len
= sectors_per_vtrack
;
208 unsigned long long read_start
= track
;
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!
219 bufaddr
= (char *) BUFFERADDR
+ byte_offset
;
222 bios_err
= biosdisk (BIOSDISK_READ
, drive
, &buf_geom
,
223 read_start
, read_len
, BUFFERSEG
);
226 buf_track
= BUF_CACHE_INVALID
;
228 if (bios_err
== BIOSDISK_ERROR_GEOMETRY
)
233 * If there was an error, try to load only the
234 * required sector(s) rather than failing completely.
237 || biosdisk (BIOSDISK_READ
, drive
, &buf_geom
,
238 sector
, slen
, BUFFERSEG
))
241 bufaddr
= (char *) BUFFERADDR
+ byte_offset
;
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
))
253 /* This is a EZD disk map sector 0 to sector 1 */
254 if (buf_track
== 0 || slen
>= 2)
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
);
263 if (biosdisk (BIOSDISK_READ
, drive
, &buf_geom
,
270 if (size
> ((num_sect
<< sector_size_bits
) - byte_offset
))
271 size
= (num_sect
<< sector_size_bits
) - byte_offset
;
274 * Instrumentation to tell which sectors were read and used.
278 unsigned long long sector_num
= sector
;
279 int length
= buf_geom
.sector_size
- byte_offset
;
282 (*disk_read_func
) (sector_num
++, byte_offset
, length
);
283 length
= size
- length
;
286 while (length
> buf_geom
.sector_size
)
288 (*disk_read_func
) (sector_num
++, 0, buf_geom
.sector_size
);
289 length
-= buf_geom
.sector_size
;
291 (*disk_read_func
) (sector_num
, 0, length
);
295 grub_memmove (buf
, bufaddr
, size
);
308 devread(unsigned long long sector
, int byte_offset
, int byte_len
, char *buf
)
311 * Check partition boundaries
313 if ((sector
+ ((byte_offset
+ byte_len
- 1) >> SECTOR_BITS
))
316 errnum
= ERR_OUTSIDE_PART
;
321 * Get the read to the beginning of a partition.
323 sector
+= byte_offset
>> SECTOR_BITS
;
324 byte_offset
&= SECTOR_SIZE
- 1;
326 #if !defined(STAGE1_5)
327 if (disk_read_hook
&& debug
)
328 printf ("<%llu, %d, %d>", sector
, byte_offset
, byte_len
);
329 #endif /* !STAGE1_5 */
332 * Call RAWREAD, which is very similar, but:
334 * -- It takes an extra parameter, the drive number.
335 * -- It requires that "sector" is relative to the beginning
337 * -- It doesn't handle offsets of more than 511 bytes into the
340 return rawread (current_drive
, part_start
+ sector
, byte_offset
,
346 rawwrite(int drive
, unsigned long long sector
, char *buf
)
350 if (biosdisk (BIOSDISK_READ
, drive
, &buf_geom
, 0, 1, SCRATCHSEG
))
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
)
363 memmove ((char *) SCRATCHADDR
, buf
, SECTOR_SIZE
);
364 if (biosdisk (BIOSDISK_WRITE
, drive
, &buf_geom
,
365 sector
, 1, SCRATCHSEG
))
371 if (sector
- sector
% buf_geom
.sectors
== buf_track
)
372 /* Clear the cache. */
373 buf_track
= BUF_CACHE_INVALID
;
379 devwrite(unsigned long long sector
, int sector_count
, char *buf
)
381 #if defined(GRUB_UTIL) && defined(__linux__)
382 if (current_partition
!= 0xFFFFFF
383 && is_disk_device (device_map
, current_drive
))
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
389 return write_to_partition (device_map
, current_drive
, current_partition
,
390 sector
, sector_count
, buf
);
393 #endif /* GRUB_UTIL && __linux__ */
397 for (i
= 0; i
< sector_count
; i
++)
399 if (! rawwrite (current_drive
, part_start
+ sector
+ i
,
400 buf
+ (i
<< SECTOR_BITS
)))
409 sane_partition (void)
412 if (current_drive
== NETWORK_DRIVE
)
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)))
425 errnum
= ERR_DEV_VALUES
;
428 #endif /* ! STAGE1_5 */
434 for (fsys_type
= 0; fsys_type
< NUM_FSYS
; fsys_type
++)
435 if ((fsys_table
[fsys_type
].mount_func
) ())
438 if (fsys_type
== NUM_FSYS
&& errnum
== ERR_NONE
)
439 errnum
= ERR_FSYS_MOUNT
;
442 if ((*(fsys_table
[fsys_type
].mount_func
)) () != 1)
444 fsys_type
= NUM_FSYS
;
445 errnum
= ERR_FSYS_MOUNT
;
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
456 make_saved_active (void)
460 if (saved_drive
& 0x80)
463 int part
= saved_partition
>> 16;
465 /* If the partition is not a primary partition, the active flag is
466 meaningless. (XXX: Really?) */
469 errnum
= ERR_DEV_VALUES
;
473 /* Read the MBR in the scratch space. */
474 if (! rawread (saved_drive
, 0, 0, SECTOR_SIZE
, mbr
))
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
)))
481 errnum
= ERR_DEV_VALUES
;
485 /* Check if the active flag is disabled. */
486 if (PC_SLICE_FLAG (mbr
, part
) != PC_SLICE_FLAG_BOOTABLE
)
490 /* Clear all the active flags in this table. */
491 for (i
= 0; i
< 4; i
++)
492 PC_SLICE_FLAG (mbr
, i
) = 0;
495 PC_SLICE_FLAG (mbr
, part
) = PC_SLICE_FLAG_BOOTABLE
;
497 /* Write back the MBR. */
498 if (! rawwrite (saved_drive
, 0, mbr
))
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
;
513 /* Hide/Unhide CURRENT_PARTITION. */
515 set_partition_hidden_flag (int hidden
)
517 unsigned long part
= 0xFFFFFF;
518 unsigned long long start
, len
, offset
, ext_offset
, gpt_offset
;
519 int entry
, type
, gpt_count
, gpt_size
;
522 /* The drive must be a hard disk. */
523 if (! (current_drive
& 0x80))
525 errnum
= ERR_BAD_ARGUMENT
;
529 /* The partition must be a PC slice. */
530 if ((current_partition
>> 16) == 0xFF
531 || (current_partition
& 0xFFFF) != 0xFFFF)
533 errnum
= ERR_BAD_ARGUMENT
;
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
))
542 /* The partition may not be a GPT partition. */
545 errnum
= ERR_BAD_ARGUMENT
;
549 if (part
== current_partition
)
553 PC_SLICE_TYPE (mbr
, entry
) |= PC_SLICE_TYPE_HIDDEN_FLAG
;
555 PC_SLICE_TYPE (mbr
, entry
) &= ~PC_SLICE_TYPE_HIDDEN_FLAG
;
557 /* Write back the MBR to the disk. */
558 buf_track
= BUF_CACHE_INVALID
;
559 if (! rawwrite (current_drive
, offset
, mbr
))
572 check_and_print_mount (void)
575 if (errnum
== ERR_FSYS_MOUNT
)
581 #endif /* STAGE1_5 */
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. */
596 next_partition (unsigned long drive
, unsigned long dest
,
597 unsigned long *partition
, int *type
,
598 unsigned long long *start
, unsigned long long *len
,
599 unsigned long long *offset
, int *entry
,
600 unsigned long long *ext_offset
,
601 unsigned long long *gpt_offset
, int *gpt_count
,
602 int *gpt_size
, char *buf
)
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);
610 /* Get next BSD partition in current PC slice. */
611 int next_bsd_partition (void)
614 int bsd_part_no
= (*partition
& 0xFF00) >> 8;
616 /* If this is the first time... */
617 if (bsd_part_no
== 0xFF)
619 /* Check if the BSD label is within current PC slice. */
620 if (*len
< BSD_LABEL_SECTOR
+ 1)
622 errnum
= ERR_BAD_PART_TABLE
;
626 /* Read the BSD label. */
627 if (! rawread (drive
, *start
+ BSD_LABEL_SECTOR
,
628 0, SECTOR_SIZE
, buf
))
631 /* Check if it is valid. */
632 if (! BSD_LABEL_CHECK_MAG (buf
))
634 errnum
= ERR_BAD_PART_TABLE
;
641 /* Search next valid BSD partition. */
642 for (i
= bsd_part_no
+ 1; i
< BSD_LABEL_NPARTS (buf
); i
++)
644 if (BSD_PART_TYPE (buf
, i
))
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);
655 if ((drive
& 0x80) && BSD_LABEL_DTYPE (buf
) == DTYPE_SCSI
)
657 #endif /* ! STAGE1_5 */
663 errnum
= ERR_NO_PART
;
667 /* Get next Solaris partition in current PC slice. */
668 int next_solaris_partition (void)
670 static unsigned long pcs_start
;
672 int sol_part_no
= (*partition
& 0xFF00) >> 8;
674 /* If this is the first time... */
675 if (sol_part_no
== 0xFF)
677 /* Check if the Solaris label is within current PC slice. */
678 if (*len
< SOL_LABEL_LOC
+ 1)
680 errnum
= ERR_BAD_PART_TABLE
;
684 /* Read the Solaris label. */
685 if (! rawread (drive
, *start
+ SOL_LABEL_LOC
, 0, SECTOR_SIZE
, buf
))
688 /* Check if it is valid. */
689 if (! SOL_LABEL_CHECK_MAG (buf
))
691 errnum
= ERR_BAD_PART_TABLE
;
696 pcs_start
= *start
; /* save the start of pc slice */
699 /* Search next valid Solaris partition. */
700 for (i
= sol_part_no
+ 1; i
< SOL_LABEL_NPARTS
; i
++)
702 if (SOL_PART_EXISTS (buf
, i
))
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);
713 errnum
= ERR_NO_PART
;
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)
721 int pc_slice_no
= (*partition
& 0xFF0000) >> 16;
723 /* If this is the first time... */
724 if (pc_slice_no
== 0xFF)
732 /* Read the MBR or the boot sector of the extended partition. */
733 if (! rawread (drive
, *offset
, 0, SECTOR_SIZE
, buf
))
736 /* Check if it is valid. */
737 if (! PC_MBR_CHECK_SIG (buf
))
739 errnum
= ERR_BAD_PART_TABLE
;
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
)
746 struct grub_gpt_header
*hdr
= (struct grub_gpt_header
*) buf
;
748 /* Read in the GPT Partition table header. */
749 if (! rawread (drive
, 1, 0, SECTOR_SIZE
, buf
))
752 if (hdr
->magic
== GPT_HEADER_MAGIC
&& hdr
->version
== 0x10000)
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
;
762 return next_gpt_slice();
766 /* This is not a valid header for a GPT partition table.
767 Re-read the MBR or the boot sector of the extended
769 if (! rawread (drive
, *offset
, 0, SECTOR_SIZE
, buf
))
774 /* Not a GPT partition. */
777 /* Increase the entry number. */
780 /* If this is out of current partition table... */
781 if (*entry
== PC_SLICE_MAX
)
785 /* Search the first extended partition in current table. */
786 for (i
= 0; i
< PC_SLICE_MAX
; i
++)
788 if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (buf
, i
)))
790 /* Found. Set the new offset and the entry number,
791 and restart this function. */
792 *offset
= *ext_offset
+ PC_SLICE_START (buf
, i
);
794 *ext_offset
= *offset
;
796 return next_pc_slice ();
800 errnum
= ERR_NO_PART
;
804 *type
= PC_SLICE_TYPE (buf
, *entry
);
805 *start
= *offset
+ PC_SLICE_START (buf
, *entry
);
806 *len
= PC_SLICE_LENGTH (buf
, *entry
);
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
))
817 *partition
= (pc_slice_no
<< 16) | 0xFFFF;
821 /* Get the next GPT slice. */
822 int next_gpt_slice (void)
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;
828 /* If this is the first time... */
829 if (pc_slice_no
== 0xFF)
838 if (*entry
>= *gpt_count
)
840 errnum
= ERR_NO_PART
;
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
))
846 } while (! (gptentry
->type1
&& gptentry
->type2
));
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;
858 /* Start the body of this function. */
861 if (current_drive
== NETWORK_DRIVE
)
865 /* check for Solaris partition */
866 if (*partition
!= 0xFFFFFF && IS_PC_SLICE_TYPE_SOLARIS (*type
& 0xff))
868 if (next_solaris_partition ())
873 if (*partition
!= 0xFFFFFF && *gpt_offset
!= 0)
874 return next_gpt_slice ();
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))
881 if (*type
== PC_SLICE_TYPE_NONE
)
882 *type
= PC_SLICE_TYPE_FREEBSD
;
884 /* Get next BSD partition, if any. */
885 if (next_bsd_partition ())
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)))
895 /* Ignore the error. */
899 return next_pc_slice ();
903 static unsigned long cur_part_offset
;
904 static unsigned long cur_part_addr
;
907 /* Open a partition. */
909 real_open_partition (int flags
)
911 unsigned long dest_partition
= current_partition
;
912 unsigned long long part_offset
;
913 unsigned long long ext_offset
;
914 unsigned long long gpt_offset
;
918 char buf
[SECTOR_SIZE
];
919 int unix_part
, pc_slice
;
921 /* For simplicity. */
922 auto int next (void);
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;
937 if (current_drive
== NETWORK_DRIVE
)
940 if (! sane_partition ())
948 /* Make sure that buf_geom is valid. */
949 if (buf_drive
!= current_drive
)
951 if (get_diskinfo (current_drive
, &buf_geom
))
953 errnum
= ERR_NO_DISK
;
956 buf_drive
= current_drive
;
957 buf_track
= BUF_CACHE_INVALID
;
960 (buf_geom
.total_sectors
> MAXUINT
) ? MAXUINT
: buf_geom
.total_sectors
;
962 /* If this is the whole disk, return here. */
963 if (! flags
&& current_partition
== 0xFFFFFF)
967 dest_partition
= 0xFFFFFF;
969 /* Initialize CURRENT_PARTITION for next_partition. */
970 current_partition
= 0xFFFFFF;
977 cur_part_offset
= part_offset
;
978 cur_part_addr
= BOOT_PART_TABLE
+ (entry
<< 4);
979 #endif /* ! STAGE1_5 */
981 /* If this is a valid partition... */
985 /* Display partition information. */
986 if (flags
&& ! IS_PC_SLICE_TYPE_EXTENDED (current_slice
))
990 if (current_drive
& 0x80)
991 grub_printf (" Partition num: %d, ",
992 current_partition
>> 16);
994 if (! IS_PC_SLICE_TYPE_BSD (current_slice
) &&
995 ! IS_PC_SLICE_TYPE_SOLARIS (current_slice
))
996 check_and_print_mount ();
1000 int saved_slice
= current_slice
;
1004 if (unix_part
== 0xFF)
1009 grub_printf ("[BSD/SOLARIS sub-partitions immediately follow]\n");
1013 grub_printf (" BSD/SOLARIS Partition num: \'%c\', ",
1015 check_and_print_mount ();
1019 grub_printf (" No BSD/SOLARIS sub-partition found, partition type 0x%x\n",
1033 if (unix_part
!= 0xFF)
1037 if (! (current_drive
& 0x80)
1038 || (dest_partition
>> 16) == pc_slice
)
1039 grub_sprintf (str
, "%c)", unix_part
+ 'a');
1041 grub_sprintf (str
, "%d,%c)",
1042 pc_slice
, unix_part
+ 'a');
1043 print_a_completion (str
);
1045 else if (! IS_PC_SLICE_TYPE_BSD (current_slice
) &&
1046 ! IS_PC_SLICE_TYPE_SOLARIS (current_slice
))
1050 grub_sprintf (str
, "%d)", pc_slice
);
1051 print_a_completion (str
);
1057 #endif /* ! STAGE1_5 */
1059 /* Check if this is the destination partition. */
1061 && (dest_partition
== current_partition
1062 || ((dest_partition
>> 16) == 0xFF
1063 && ((dest_partition
>> 8) & 0xFF) == unix_part
)))
1071 if (! (current_drive
& 0x80))
1073 current_partition
= 0xFFFFFF;
1074 check_and_print_mount ();
1080 #endif /* ! STAGE1_5 */
1087 open_partition (void)
1089 return real_open_partition (0);
1094 /* XX used for device completion in 'set_device' and 'print_completions' */
1095 static int incomplete
, disk_choice
;
1098 PART_UNSPECIFIED
= 0,
1103 #endif /* ! STAGE1_5 */
1106 set_device (char *device
)
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;
1114 /* If DRIVE is disabled, use SAVED_DRIVE instead. */
1115 if (drive
== GRUB_INVALID_DRIVE
)
1116 current_drive
= saved_drive
;
1118 current_drive
= drive
;
1120 /* The `partition' part must always have a valid number. */
1121 current_partition
= partition
;
1123 return device
+ sizeof (unsigned long);
1125 #else /* ! STAGE1_5 */
1131 part_choice
= PART_UNSPECIFIED
;
1132 current_drive
= saved_drive
;
1133 current_partition
= 0xFFFFFF;
1135 if (*device
== '(' && !*(device
+ 1))
1136 /* user has given '(' only, let disk_choice handle what disks we have */
1139 if (*device
== '(' && *(++device
))
1141 if (*device
!= ',' && *device
!= ')')
1144 #ifdef SUPPORT_NETBOOT
1145 if (*device
== 'f' || *device
== 'h'
1146 || (*device
== 'n' && network_ready
)
1147 || (*device
== 'c' && cdrom_drive
!= GRUB_INVALID_DRIVE
))
1149 if (*device
== 'f' || *device
== 'h'
1150 || (*device
== 'c' && cdrom_drive
!= GRUB_INVALID_DRIVE
))
1151 #endif /* SUPPORT_NETBOOT */
1153 /* user has given '([fhn]', check for resp. add 'd' and
1154 let disk_choice handle what disks we have */
1162 else if (*(device
+ 1) == 'd' && !*(device
+ 2))
1168 #ifdef SUPPORT_NETBOOT
1169 || (*device
== 'n' && network_ready
)
1171 || (*device
== 'c' && cdrom_drive
!= GRUB_INVALID_DRIVE
))
1172 && (device
+= 2, (*(device
- 1) != 'd')))
1173 errnum
= ERR_NUMBER_PARSING
;
1175 #ifdef SUPPORT_NETBOOT
1176 if (ch
== 'n' && network_ready
)
1177 current_drive
= NETWORK_DRIVE
;
1179 #endif /* SUPPORT_NETBOOT */
1181 if (ch
== 'c' && cdrom_drive
!= GRUB_INVALID_DRIVE
)
1182 current_drive
= cdrom_drive
;
1185 safe_parse_maxint (&device
, (int *) ¤t_drive
);
1189 current_drive
+= 0x80;
1199 part_choice
= PART_CHOSEN
;
1202 else if (*device
== ',')
1204 /* Either an absolute PC, BSD, or Solaris partition. */
1209 if (*device
>= '0' && *device
<= '9')
1212 current_partition
= 0;
1214 if (!(current_drive
& 0x80)
1215 || !safe_parse_maxint (&device
, (int *) ¤t_partition
)
1216 || current_partition
> 254)
1218 errnum
= ERR_DEV_FORMAT
;
1222 current_partition
= (current_partition
<< 16) + 0xFFFF;
1227 if (*device
>= 'a' && *device
<= 'p')
1229 current_partition
= (((*(device
++) - 'a') << 8)
1230 | (current_partition
& 0xFF00FF));
1233 else if (*device
>= 'a' && *device
<= 'p')
1236 current_partition
= ((*(device
++) - 'a') << 8) | 0xFF00FF;
1241 if (part_choice
== PART_DISK
)
1243 current_partition
= saved_partition
;
1252 if (! sane_partition ())
1261 errnum
= ERR_DEV_FORMAT
;
1266 #endif /* ! STAGE1_5 */
1270 * This performs a "mount" on the current device, both drive and partition
1277 if (open_partition ())
1280 if (errnum
!= ERR_NONE
)
1289 set_bootdev (int hdbias
)
1293 /* Copy the boot partition information to 0x7be-0x7fd for chain-loading. */
1294 if ((saved_drive
& 0x80) && cur_part_addr
)
1296 if (rawread (saved_drive
, cur_part_offset
,
1297 0, SECTOR_SIZE
, (char *) SCRATCHADDR
))
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
)
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;
1313 *((unsigned char *) cur_part_addr
) = PC_SLICE_FLAG_BOOTABLE
;
1314 boot_part_addr
= cur_part_addr
;
1321 * Set BSD boot device.
1323 i
= (saved_partition
>> 16) + 2;
1324 if (saved_partition
== 0xFFFFFF)
1326 else if ((saved_partition
>> 16) == 0xFF)
1329 /* FIXME: extremely evil hack!!! */
1331 if (saved_drive
& 0x80)
1334 return MAKEBOOTDEV (j
, (i
>> 4), (i
& 0xF),
1335 ((saved_drive
- hdbias
) & 0x7F),
1336 ((saved_partition
>> 8) & 0xFF));
1338 #endif /* STAGE1_5 */
1342 setup_part (char *filename
)
1346 if (! (filename
= set_device (filename
)))
1348 current_drive
= GRUB_INVALID_DRIVE
;
1352 # ifndef NO_BLOCK_FILES
1353 if (*filename
!= '/')
1356 # endif /* ! NO_BLOCK_FILES */
1359 #else /* ! STAGE1_5 */
1361 if (*filename
== '(')
1363 if ((filename
= set_device (filename
)) == 0)
1365 current_drive
= GRUB_INVALID_DRIVE
;
1368 # ifndef NO_BLOCK_FILES
1369 if (*filename
!= '/' && current_drive
!= NETWORK_DRIVE
)
1372 # endif /* ! NO_BLOCK_FILES */
1375 else if (saved_drive
!= current_drive
1376 || saved_partition
!= current_partition
1377 || (*filename
== '/' && fsys_type
== NUM_FSYS
)
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
)
1388 # endif /* ! NO_BLOCK_FILES */
1392 #endif /* ! STAGE1_5 */
1394 if (errnum
&& (*filename
== '/' || errnum
!= ERR_FSYS_MOUNT
))
1400 if (!sane_partition ())
1410 * This prints the filesystem type or gives relevant information.
1414 print_fsys_type (void)
1416 if (! do_completion
)
1418 grub_printf (" Filesystem type ");
1420 if (fsys_type
!= NUM_FSYS
)
1421 grub_printf ("is %s, ", fsys_table
[fsys_type
].name
);
1423 grub_printf ("unknown, ");
1425 if (current_partition
== 0xFFFFFF)
1426 grub_printf ("using whole disk\n");
1428 grub_printf ("partition type 0x%x\n", current_slice
& 0xFF);
1431 #endif /* STAGE1_5 */
1434 /* If DO_COMPLETION is true, just print NAME. Otherwise save the unique
1435 part into UNIQUE_STRING. */
1437 print_a_completion (char *name
)
1439 /* If NAME is "." or "..", do not count it. */
1440 if (grub_strcmp (name
, ".") == 0 || grub_strcmp (name
, "..") == 0)
1445 char *buf
= unique_string
;
1448 while ((*buf
++ = *name
++))
1452 while (*buf
&& (*buf
== *name
))
1457 /* mismatch, strip it. */
1462 grub_printf (" %s", name
);
1468 * This lists the possible completions of a device string, filename, or
1469 * any sane combination of the two.
1473 print_completions (int is_filename
, int is_completion
)
1475 char *buf
= (char *) COMPLETION_BUF
;
1478 unique_string
= (char *) UNIQUE_BUF
;
1481 do_completion
= is_completion
;
1485 /* Print the completions of builtin commands. */
1486 struct builtin
**builtin
;
1488 if (! is_completion
)
1489 grub_printf (" Possible commands are:");
1491 for (builtin
= builtin_table
; (*builtin
); builtin
++)
1493 /* If *BUILTIN cannot be run in the command-line, skip it. */
1494 if (! ((*builtin
)->flags
& BUILTIN_CMDLINE
))
1497 if (substring (buf
, (*builtin
)->name
) <= 0)
1498 print_a_completion ((*builtin
)->name
);
1501 if (is_completion
&& *unique_string
)
1505 char *u
= unique_string
+ grub_strlen (unique_string
);
1511 grub_strcpy (buf
, unique_string
);
1514 if (! is_completion
)
1515 grub_putchar ('\n');
1525 if (*buf
== '/' || (ptr
= set_device (buf
)) || incomplete
)
1529 if (*buf
== '(' && (incomplete
|| ! *ptr
))
1533 /* disk completions */
1535 struct geometry geom
;
1537 if (! is_completion
)
1538 grub_printf (" Possible disks are: ");
1542 #ifdef SUPPORT_NETBOOT
1544 #endif /* SUPPORT_NETBOOT */
1547 for (i
= (ptr
&& (*(ptr
-1) == 'd' && *(ptr
-2) == 'h') ? 1:0);
1548 i
< (ptr
&& (*(ptr
-1) == 'd' && *(ptr
-2) == 'f') ? 1:2);
1551 for (j
= 0; j
< 8; j
++)
1553 disk_no
= (i
* 0x80) + j
;
1554 if ((disk_choice
|| disk_no
== current_drive
)
1555 && ! get_diskinfo (disk_no
, &geom
))
1559 grub_sprintf (dev_name
, "%cd%d", i
? 'h':'f', j
);
1560 print_a_completion (dev_name
);
1566 if (cdrom_drive
!= GRUB_INVALID_DRIVE
1567 && (disk_choice
|| cdrom_drive
== current_drive
)
1570 || (*(ptr
-1) == 'd' && *(ptr
-2) == 'c')))
1571 print_a_completion ("cd");
1573 # ifdef SUPPORT_NETBOOT
1575 && (disk_choice
|| NETWORK_DRIVE
== current_drive
)
1578 || (*(ptr
-1) == 'd' && *(ptr
-2) == 'n')))
1579 print_a_completion ("nd");
1580 # endif /* SUPPORT_NETBOOT */
1582 if (is_completion
&& *unique_string
)
1588 grub_strcpy (ptr
, unique_string
);
1591 ptr
+= grub_strlen (ptr
);
1592 if (*unique_string
== 'h')
1605 if (! is_completion
)
1606 grub_putchar ('\n');
1610 /* partition completions */
1611 if (part_choice
== PART_CHOSEN
1612 && open_partition ()
1613 && ! IS_PC_SLICE_TYPE_BSD (current_slice
))
1616 ptr
= buf
+ grub_strlen (buf
);
1617 if (*(ptr
- 1) != ')')
1625 if (! is_completion
)
1626 grub_printf (" Possible partitions are:\n");
1627 real_open_partition (1);
1629 if (is_completion
&& *unique_string
)
1632 while (*ptr
++ != ',')
1634 grub_strcpy (ptr
, unique_string
);
1639 else if (ptr
&& *ptr
== '/')
1641 /* filename completions */
1642 if (! is_completion
)
1643 grub_printf (" Possible files are:");
1647 if (is_completion
&& *unique_string
)
1649 ptr
+= grub_strlen (ptr
);
1654 grub_strcpy (ptr
, unique_string
);
1658 ptr
+= grub_strlen (unique_string
);
1660 /* Check if the file UNIQUE_STRING is a directory. */
1666 /* Restore the original unique value. */
1679 if (! is_completion
)
1680 grub_putchar ('\n');
1683 errnum
= ERR_BAD_FILENAME
;
1693 #endif /* STAGE1_5 */
1697 * This is the generic file open function.
1701 grub_open (char *filename
)
1703 #ifndef NO_DECOMPRESSION
1704 compressed_file
= 0;
1705 #endif /* NO_DECOMPRESSION */
1707 /* if any "dir" function uses/sets filepos, it must
1708 set it to zero before returning if opening a file! */
1711 if (!(filename
= setup_part (filename
)))
1714 #ifndef NO_BLOCK_FILES
1716 #endif /* NO_BLOCK_FILES */
1718 /* This accounts for partial filesystem implementations. */
1721 if (*filename
!= '/' && current_drive
!= NETWORK_DRIVE
)
1723 #ifndef NO_BLOCK_FILES
1724 char *ptr
= filename
;
1725 int tmp
, list_addr
= BLK_BLKLIST_START
;
1728 while (list_addr
< BLK_MAX_ADDR
)
1731 safe_parse_maxint (&ptr
, &tmp
);
1736 if ((*ptr
&& *ptr
!= '/' && !isspace (*ptr
))
1737 || tmp
== 0 || tmp
> filemax
)
1738 errnum
= ERR_BAD_FILENAME
;
1745 /* since we use the same filesystem buffer, mark it to
1747 fsys_type
= NUM_FSYS
;
1749 BLK_BLKSTART (list_addr
) = tmp
;
1752 if (!safe_parse_maxint (&ptr
, &tmp
)
1754 || (*ptr
&& *ptr
!= ',' && *ptr
!= '/' && !isspace (*ptr
)))
1756 errnum
= ERR_BAD_FILENAME
;
1760 BLK_BLKLENGTH (list_addr
) = tmp
;
1762 filemax
+= (tmp
* SECTOR_SIZE
);
1763 list_addr
+= BLK_BLKLIST_INC_VAL
;
1771 if (list_addr
< BLK_MAX_ADDR
&& ptr
!= filename
&& !errnum
)
1774 BLK_CUR_FILEPOS
= 0;
1775 BLK_CUR_BLKLIST
= BLK_BLKLIST_START
;
1778 #ifndef NO_DECOMPRESSION
1779 return gunzip_test_header ();
1780 #else /* NO_DECOMPRESSION */
1782 #endif /* NO_DECOMPRESSION */
1784 #else /* NO_BLOCK_FILES */
1785 errnum
= ERR_BAD_FILENAME
;
1786 #endif /* NO_BLOCK_FILES */
1789 if (!errnum
&& fsys_type
== NUM_FSYS
)
1790 errnum
= ERR_FSYS_MOUNT
;
1793 /* set "dir" function to open a file */
1794 print_possibilities
= 0;
1797 if (!errnum
&& (*(fsys_table
[fsys_type
].dir_func
)) (filename
))
1799 #ifndef NO_DECOMPRESSION
1800 return gunzip_test_header ();
1801 #else /* NO_DECOMPRESSION */
1803 #endif /* NO_DECOMPRESSION */
1811 grub_read (char *buf
, int len
)
1813 /* Make sure "filepos" is a sane value */
1814 if ((filepos
< 0) || (filepos
> filemax
))
1817 /* Make sure "len" is a sane value */
1818 if ((len
< 0) || (len
> (filemax
- filepos
)))
1819 len
= filemax
- filepos
;
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
)
1826 errnum
= ERR_FILELENGTH
;
1830 #ifndef NO_DECOMPRESSION
1831 if (compressed_file
)
1832 return gunzip_read (buf
, len
);
1833 #endif /* NO_DECOMPRESSION */
1835 #ifndef NO_BLOCK_FILES
1838 int size
, off
, ret
= 0;
1840 while (len
&& !errnum
)
1842 /* we may need to look for the right block in the list(s) */
1843 if (filepos
< BLK_CUR_FILEPOS
)
1845 BLK_CUR_FILEPOS
= 0;
1846 BLK_CUR_BLKLIST
= BLK_BLKLIST_START
;
1850 /* run BLK_CUR_FILEPOS up to filepos */
1851 while (filepos
> BLK_CUR_FILEPOS
)
1853 if ((filepos
- (BLK_CUR_FILEPOS
& ~(SECTOR_SIZE
- 1)))
1856 BLK_CUR_FILEPOS
+= SECTOR_SIZE
;
1859 if (BLK_CUR_BLKNUM
>= BLK_BLKLENGTH (BLK_CUR_BLKLIST
))
1861 BLK_CUR_BLKLIST
+= BLK_BLKLIST_INC_VAL
;
1866 BLK_CUR_FILEPOS
= filepos
;
1869 off
= filepos
& (SECTOR_SIZE
- 1);
1870 size
= ((BLK_BLKLENGTH (BLK_CUR_BLKLIST
) - BLK_CUR_BLKNUM
)
1871 * SECTOR_SIZE
) - off
;
1875 disk_read_func
= disk_read_hook
;
1877 /* read current block and put it in the right place in memory */
1878 devread (BLK_BLKSTART (BLK_CUR_BLKLIST
) + BLK_CUR_BLKNUM
,
1881 disk_read_func
= NULL
;
1894 #endif /* NO_BLOCK_FILES */
1896 if (fsys_type
== NUM_FSYS
)
1898 errnum
= ERR_FSYS_MOUNT
;
1902 return (*(fsys_table
[fsys_type
].read_func
)) (buf
, len
);
1906 /* Reposition a file offset. */
1908 grub_seek (int offset
)
1910 if (offset
> filemax
|| offset
< 0)
1920 #ifndef NO_DECOMPRESSION
1921 compressed_file
= 0;
1922 #endif /* NO_DECOMPRESSION */
1924 if (!(dirname
= setup_part (dirname
)))
1927 if (*dirname
!= '/')
1928 errnum
= ERR_BAD_FILENAME
;
1930 if (fsys_type
== NUM_FSYS
)
1931 errnum
= ERR_FSYS_MOUNT
;
1936 /* set "dir" function to list completions */
1937 print_possibilities
= 1;
1939 return (*(fsys_table
[fsys_type
].dir_func
)) (dirname
);
1941 #endif /* STAGE1_5 */
1946 #ifndef NO_BLOCK_FILES
1949 #endif /* NO_BLOCK_FILES */
1951 if (fsys_table
[fsys_type
].close_func
!= 0)
1952 (*(fsys_table
[fsys_type
].close_func
)) ();