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