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 slen = ((byte_offset + byte_len + buf_geom.sector_size - 1) 189 >> sector_size_bits); 190 191 /* Eliminate a buffer overflow. */ 192 if ((buf_geom.sectors << sector_size_bits) > BUFFERLEN) 193 sectors_per_vtrack = (BUFFERLEN >> sector_size_bits); 194 else 195 sectors_per_vtrack = buf_geom.sectors; 196 197 /* Get the first sector of track. */ 198 soff = sector % sectors_per_vtrack; 199 track = sector - soff; 200 num_sect = sectors_per_vtrack - soff; 201 bufaddr = ((char *) BUFFERADDR 202 + (soff << sector_size_bits) + byte_offset); 203 204 if (track != buf_track) 205 { 206 int bios_err, read_len = sectors_per_vtrack; 207 unsigned int read_start = track; 208 209 /* 210 * If there's more than one read in this entire loop, then 211 * only make the earlier reads for the portion needed. This 212 * saves filling the buffer with data that won't be used! 213 */ 214 if (slen > num_sect) 215 { 216 read_start = sector; 217 read_len = num_sect; 218 bufaddr = (char *) BUFFERADDR + byte_offset; 219 } 220 221 bios_err = biosdisk (BIOSDISK_READ, drive, &buf_geom, 222 read_start, read_len, BUFFERSEG); 223 if (bios_err) 224 { 225 buf_track = BUF_CACHE_INVALID; 226 227 if (bios_err == BIOSDISK_ERROR_GEOMETRY) 228 errnum = ERR_GEOM; 229 else 230 { 231 /* 232 * If there was an error, try to load only the 233 * required sector(s) rather than failing completely. 234 */ 235 if (slen > num_sect 236 || biosdisk (BIOSDISK_READ, drive, &buf_geom, 237 sector, slen, BUFFERSEG)) 238 errnum = ERR_READ; 239 240 bufaddr = (char *) BUFFERADDR + byte_offset; 241 } 242 } 243 else 244 buf_track = track; 245 246 if ((buf_track == 0 || sector == 0) 247 && (PC_SLICE_TYPE (BUFFERADDR, 0) == PC_SLICE_TYPE_EZD 248 || PC_SLICE_TYPE (BUFFERADDR, 1) == PC_SLICE_TYPE_EZD 249 || PC_SLICE_TYPE (BUFFERADDR, 2) == PC_SLICE_TYPE_EZD 250 || PC_SLICE_TYPE (BUFFERADDR, 3) == PC_SLICE_TYPE_EZD)) 251 { 252 /* This is a EZD disk map sector 0 to sector 1 */ 253 if (buf_track == 0 || slen >= 2) 254 { 255 /* We already read the sector 1, copy it to sector 0 */ 256 memmove ((char *) BUFFERADDR, 257 (char *) BUFFERADDR + buf_geom.sector_size, 258 buf_geom.sector_size); 259 } 260 else 261 { 262 if (biosdisk (BIOSDISK_READ, drive, &buf_geom, 263 1, 1, BUFFERSEG)) 264 errnum = ERR_READ; 265 } 266 } 267 } 268 269 if (size > ((num_sect << sector_size_bits) - byte_offset)) 270 size = (num_sect << sector_size_bits) - byte_offset; 271 272 /* 273 * Instrumentation to tell which sectors were read and used. 274 */ 275 if (disk_read_func) 276 { 277 unsigned int sector_num = sector; 278 int length = buf_geom.sector_size - byte_offset; 279 if (length > size) 280 length = size; 281 (*disk_read_func) (sector_num++, byte_offset, length); 282 length = size - length; 283 if (length > 0) 284 { 285 while (length > buf_geom.sector_size) 286 { 287 (*disk_read_func) (sector_num++, 0, buf_geom.sector_size); 288 length -= buf_geom.sector_size; 289 } 290 (*disk_read_func) (sector_num, 0, length); 291 } 292 } 293 294 grub_memmove (buf, bufaddr, size); 295 296 buf += size; 297 byte_len -= size; 298 sector += num_sect; 299 byte_offset = 0; 300 } 301 302 return (!errnum); 303 } 304 305 306 int 307 devread(unsigned int sector, int byte_offset, int byte_len, char *buf) 308 { 309 /* 310 * Check partition boundaries 311 */ 312 if ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS)) 313 >= part_length) 314 { 315 errnum = ERR_OUTSIDE_PART; 316 return 0; 317 } 318 319 /* 320 * Get the read to the beginning of a partition. 321 */ 322 sector += byte_offset >> SECTOR_BITS; 323 byte_offset &= SECTOR_SIZE - 1; 324 325 #if !defined(STAGE1_5) 326 if (disk_read_hook && debug) 327 printf ("<%u, %d, %d>", sector, byte_offset, byte_len); 328 #endif /* !STAGE1_5 */ 329 330 /* 331 * Call RAWREAD, which is very similar, but: 332 * 333 * -- It takes an extra parameter, the drive number. 334 * -- It requires that "sector" is relative to the beginning 335 * of the disk. 336 * -- It doesn't handle offsets of more than 511 bytes into the 337 * sector. 338 */ 339 return rawread (current_drive, part_start + sector, byte_offset, 340 byte_len, buf); 341 } 342 343 #ifndef STAGE1_5 344 int 345 rawwrite(int drive, unsigned int sector, char *buf) 346 { 347 if (sector == 0) 348 { 349 if (biosdisk (BIOSDISK_READ, drive, &buf_geom, 0, 1, SCRATCHSEG)) 350 { 351 errnum = ERR_WRITE; 352 return 0; 353 } 354 355 if (PC_SLICE_TYPE (SCRATCHADDR, 0) == PC_SLICE_TYPE_EZD 356 || PC_SLICE_TYPE (SCRATCHADDR, 1) == PC_SLICE_TYPE_EZD 357 || PC_SLICE_TYPE (SCRATCHADDR, 2) == PC_SLICE_TYPE_EZD 358 || PC_SLICE_TYPE (SCRATCHADDR, 3) == PC_SLICE_TYPE_EZD) 359 sector = 1; 360 } 361 362 memmove ((char *) SCRATCHADDR, buf, SECTOR_SIZE); 363 if (biosdisk (BIOSDISK_WRITE, drive, &buf_geom, 364 sector, 1, SCRATCHSEG)) 365 { 366 errnum = ERR_WRITE; 367 return 0; 368 } 369 370 if (sector - sector % buf_geom.sectors == buf_track) 371 /* Clear the cache. */ 372 buf_track = BUF_CACHE_INVALID; 373 374 return 1; 375 } 376 377 int 378 devwrite(unsigned int sector, int sector_count, char *buf) 379 { 380 #if defined(GRUB_UTIL) && defined(__linux__) 381 if (current_partition != 0xFFFFFF 382 && is_disk_device (device_map, current_drive)) 383 { 384 /* If the grub shell is running under Linux and the user wants to 385 embed a Stage 1.5 into a partition instead of a MBR, use system 386 calls directly instead of biosdisk, because of the bug in 387 Linux. *sigh* */ 388 return write_to_partition (device_map, current_drive, current_partition, 389 sector, sector_count, buf); 390 } 391 else 392 #endif /* GRUB_UTIL && __linux__ */ 393 { 394 int i; 395 396 for (i = 0; i < sector_count; i++) 397 { 398 if (! rawwrite (current_drive, part_start + sector + i, 399 buf + (i << SECTOR_BITS))) 400 return 0; 401 402 } 403 return 1; 404 } 405 } 406 407 static int 408 sane_partition (void) 409 { 410 /* network drive */ 411 if (current_drive == NETWORK_DRIVE) 412 return 1; 413 414 if (!(current_partition & 0xFF000000uL) 415 && ((current_drive & 0xFFFFFF7F) < 8 416 || current_drive == cdrom_drive) 417 && (current_partition & 0xFF) == 0xFF 418 && ((current_partition & 0xFF00) == 0xFF00 419 || (current_partition & 0xFF00) < 0x1000) 420 && ((current_partition >> 16) == 0xFF 421 || (current_drive & 0x80))) 422 return 1; 423 424 errnum = ERR_DEV_VALUES; 425 return 0; 426 } 427 #endif /* ! STAGE1_5 */ 428 429 static void 430 attempt_mount (void) 431 { 432 #ifndef STAGE1_5 433 for (fsys_type = 0; fsys_type < NUM_FSYS; fsys_type++) 434 { 435 /* 436 * (re)set errnum to 0 in order to clear any state that may have 437 * been left from a previous mount (or other) routine. 438 */ 439 errnum = 0; 440 if ((fsys_table[fsys_type].mount_func) ()) 441 break; 442 } 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 = 878 (buf_geom.total_sectors > MAXUINT) ? MAXUINT : buf_geom.total_sectors; 879 880 /* If this is the whole disk, return here. */ 881 if (! flags && current_partition == 0xFFFFFF) 882 return 1; 883 884 if (flags) 885 dest_partition = 0xFFFFFF; 886 887 /* Initialize CURRENT_PARTITION for next_partition. */ 888 current_partition = 0xFFFFFF; 889 890 while (next ()) 891 { 892 #ifndef STAGE1_5 893 loop_start: 894 895 cur_part_offset = part_offset; 896 cur_part_addr = BOOT_PART_TABLE + (entry << 4); 897 #endif /* ! STAGE1_5 */ 898 899 /* If this is a valid partition... */ 900 if (current_slice) 901 { 902 #ifndef STAGE1_5 903 /* Display partition information. */ 904 if (flags && ! IS_PC_SLICE_TYPE_EXTENDED (current_slice)) 905 { 906 if (! do_completion) 907 { 908 if (current_drive & 0x80) 909 grub_printf (" Partition num: %d, ", 910 current_partition >> 16); 911 912 if (! IS_PC_SLICE_TYPE_BSD (current_slice) && 913 ! IS_PC_SLICE_TYPE_SOLARIS (current_slice)) 914 check_and_print_mount (); 915 else 916 { 917 int got_part = 0; 918 int saved_slice = current_slice; 919 920 while (next ()) 921 { 922 if (unix_part == 0xFF) 923 break; 924 925 if (! got_part) 926 { 927 grub_printf ("[BSD/SOLARIS sub-partitions immediately follow]\n"); 928 got_part = 1; 929 } 930 931 grub_printf (" BSD/SOLARIS Partition num: \'%c\', ", 932 unix_part + 'a'); 933 check_and_print_mount (); 934 } 935 936 if (! got_part) 937 grub_printf (" No BSD/SOLARIS sub-partition found, partition type 0x%x\n", 938 saved_slice); 939 940 if (errnum) 941 { 942 errnum = ERR_NONE; 943 break; 944 } 945 946 goto loop_start; 947 } 948 } 949 else 950 { 951 if (unix_part != 0xFF) 952 { 953 char str[16]; 954 955 if (! (current_drive & 0x80) 956 || (dest_partition >> 16) == pc_slice) 957 grub_sprintf (str, "%c)", unix_part + 'a'); 958 else 959 grub_sprintf (str, "%d,%c)", 960 pc_slice, unix_part + 'a'); 961 print_a_completion (str); 962 } 963 else if (! IS_PC_SLICE_TYPE_BSD (current_slice) && 964 ! IS_PC_SLICE_TYPE_SOLARIS (current_slice)) 965 { 966 char str[8]; 967 968 grub_sprintf (str, "%d)", pc_slice); 969 print_a_completion (str); 970 } 971 } 972 } 973 974 errnum = ERR_NONE; 975 #endif /* ! STAGE1_5 */ 976 977 /* Check if this is the destination partition. */ 978 if (! flags 979 && (dest_partition == current_partition 980 || ((dest_partition >> 16) == 0xFF 981 && ((dest_partition >> 8) & 0xFF) == unix_part))) 982 return 1; 983 } 984 } 985 986 #ifndef STAGE1_5 987 if (flags) 988 { 989 if (! (current_drive & 0x80)) 990 { 991 current_partition = 0xFFFFFF; 992 check_and_print_mount (); 993 } 994 995 errnum = ERR_NONE; 996 return 1; 997 } 998 #endif /* ! STAGE1_5 */ 999 1000 return 0; 1001 } 1002 1003 1004 int 1005 open_partition (void) 1006 { 1007 return real_open_partition (0); 1008 } 1009 1010 1011 #ifndef STAGE1_5 1012 /* XX used for device completion in 'set_device' and 'print_completions' */ 1013 static int incomplete, disk_choice; 1014 static enum 1015 { 1016 PART_UNSPECIFIED = 0, 1017 PART_DISK, 1018 PART_CHOSEN, 1019 } 1020 part_choice; 1021 #endif /* ! STAGE1_5 */ 1022 1023 char * 1024 set_device (char *device) 1025 { 1026 #ifdef STAGE1_5 1027 /* In Stage 1.5, the first 4 bytes of FILENAME has a device number. */ 1028 unsigned long dev = *((unsigned long *) device); 1029 int drive = (dev >> 24) & 0xFF; 1030 int partition = dev & 0xFFFFFF; 1031 1032 /* If DRIVE is disabled, use SAVED_DRIVE instead. */ 1033 if (drive == GRUB_INVALID_DRIVE) 1034 current_drive = saved_drive; 1035 else 1036 current_drive = drive; 1037 1038 /* The `partition' part must always have a valid number. */ 1039 current_partition = partition; 1040 1041 return device + sizeof (unsigned long); 1042 1043 #else /* ! STAGE1_5 */ 1044 1045 int result = 0; 1046 1047 incomplete = 0; 1048 disk_choice = 1; 1049 part_choice = PART_UNSPECIFIED; 1050 current_drive = saved_drive; 1051 current_partition = 0xFFFFFF; 1052 1053 if (*device == '(' && !*(device + 1)) 1054 /* user has given '(' only, let disk_choice handle what disks we have */ 1055 return device + 1; 1056 1057 if (*device == '(' && *(++device)) 1058 { 1059 if (*device != ',' && *device != ')') 1060 { 1061 char ch = *device; 1062 #ifdef SUPPORT_NETBOOT 1063 if (*device == 'f' || *device == 'h' 1064 || (*device == 'n' && network_ready) 1065 || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE)) 1066 #else 1067 if (*device == 'f' || *device == 'h' 1068 || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE)) 1069 #endif /* SUPPORT_NETBOOT */ 1070 { 1071 /* user has given '([fhn]', check for resp. add 'd' and 1072 let disk_choice handle what disks we have */ 1073 if (!*(device + 1)) 1074 { 1075 device++; 1076 *device++ = 'd'; 1077 *device = '\0'; 1078 return device; 1079 } 1080 else if (*(device + 1) == 'd' && !*(device + 2)) 1081 return device + 2; 1082 } 1083 1084 if ((*device == 'f' 1085 || *device == 'h' 1086 #ifdef SUPPORT_NETBOOT 1087 || (*device == 'n' && network_ready) 1088 #endif 1089 || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE)) 1090 && (device += 2, (*(device - 1) != 'd'))) 1091 errnum = ERR_NUMBER_PARSING; 1092 1093 #ifdef SUPPORT_NETBOOT 1094 if (ch == 'n' && network_ready) 1095 current_drive = NETWORK_DRIVE; 1096 else 1097 #endif /* SUPPORT_NETBOOT */ 1098 { 1099 if (ch == 'c' && cdrom_drive != GRUB_INVALID_DRIVE) 1100 current_drive = cdrom_drive; 1101 else 1102 { 1103 safe_parse_maxint (&device, (int *) ¤t_drive); 1104 1105 disk_choice = 0; 1106 if (ch == 'h') 1107 current_drive += 0x80; 1108 } 1109 } 1110 } 1111 1112 if (errnum) 1113 return 0; 1114 1115 if (*device == ')') 1116 { 1117 part_choice = PART_CHOSEN; 1118 result = 1; 1119 } 1120 else if (*device == ',') 1121 { 1122 /* Either an absolute PC, BSD, or Solaris partition. */ 1123 disk_choice = 0; 1124 part_choice ++; 1125 device++; 1126 1127 if (*device >= '0' && *device <= '9') 1128 { 1129 part_choice ++; 1130 current_partition = 0; 1131 1132 if (!(current_drive & 0x80) 1133 || !safe_parse_maxint (&device, (int *) ¤t_partition) 1134 || current_partition > 254) 1135 { 1136 errnum = ERR_DEV_FORMAT; 1137 return 0; 1138 } 1139 1140 current_partition = (current_partition << 16) + 0xFFFF; 1141 1142 if (*device == ',') 1143 device++; 1144 1145 if (*device >= 'a' && *device <= 'p') 1146 { 1147 current_partition = (((*(device++) - 'a') << 8) 1148 | (current_partition & 0xFF00FF)); 1149 } 1150 } 1151 else if (*device >= 'a' && *device <= 'p') 1152 { 1153 part_choice ++; 1154 current_partition = ((*(device++) - 'a') << 8) | 0xFF00FF; 1155 } 1156 1157 if (*device == ')') 1158 { 1159 if (part_choice == PART_DISK) 1160 { 1161 current_partition = saved_partition; 1162 part_choice ++; 1163 } 1164 1165 result = 1; 1166 } 1167 } 1168 } 1169 1170 if (! sane_partition ()) 1171 return 0; 1172 1173 if (result) 1174 return device + 1; 1175 else 1176 { 1177 if (!*device) 1178 incomplete = 1; 1179 errnum = ERR_DEV_FORMAT; 1180 } 1181 1182 return 0; 1183 1184 #endif /* ! STAGE1_5 */ 1185 } 1186 1187 /* 1188 * This performs a "mount" on the current device, both drive and partition 1189 * number. 1190 */ 1191 1192 int 1193 open_device (void) 1194 { 1195 if (open_partition ()) 1196 attempt_mount (); 1197 1198 if (errnum != ERR_NONE) 1199 return 0; 1200 1201 return 1; 1202 } 1203 1204 1205 #ifndef STAGE1_5 1206 int 1207 set_bootdev (int hdbias) 1208 { 1209 int i, j; 1210 1211 /* Copy the boot partition information to 0x7be-0x7fd for chain-loading. */ 1212 if ((saved_drive & 0x80) && cur_part_addr) 1213 { 1214 if (rawread (saved_drive, cur_part_offset, 1215 0, SECTOR_SIZE, (char *) SCRATCHADDR)) 1216 { 1217 char *dst, *src; 1218 1219 /* Need only the partition table. 1220 XXX: We cannot use grub_memmove because BOOT_PART_TABLE 1221 (0x07be) is less than 0x1000. */ 1222 dst = (char *) BOOT_PART_TABLE; 1223 src = (char *) SCRATCHADDR + BOOTSEC_PART_OFFSET; 1224 while (dst < (char *) BOOT_PART_TABLE + BOOTSEC_PART_LENGTH) 1225 *dst++ = *src++; 1226 1227 /* Set the active flag of the booted partition. */ 1228 for (i = 0; i < 4; i++) 1229 PC_SLICE_FLAG (BOOT_PART_TABLE, i) = 0; 1230 1231 *((unsigned char *) cur_part_addr) = PC_SLICE_FLAG_BOOTABLE; 1232 boot_part_addr = cur_part_addr; 1233 } 1234 else 1235 return 0; 1236 } 1237 1238 /* 1239 * Set BSD boot device. 1240 */ 1241 i = (saved_partition >> 16) + 2; 1242 if (saved_partition == 0xFFFFFF) 1243 i = 1; 1244 else if ((saved_partition >> 16) == 0xFF) 1245 i = 0; 1246 1247 /* FIXME: extremely evil hack!!! */ 1248 j = 2; 1249 if (saved_drive & 0x80) 1250 j = bsd_evil_hack; 1251 1252 return MAKEBOOTDEV (j, (i >> 4), (i & 0xF), 1253 ((saved_drive - hdbias) & 0x7F), 1254 ((saved_partition >> 8) & 0xFF)); 1255 } 1256 #endif /* STAGE1_5 */ 1257 1258 1259 static char * 1260 setup_part (char *filename) 1261 { 1262 #ifdef STAGE1_5 1263 1264 if (! (filename = set_device (filename))) 1265 { 1266 current_drive = GRUB_INVALID_DRIVE; 1267 return 0; 1268 } 1269 1270 # ifndef NO_BLOCK_FILES 1271 if (*filename != '/') 1272 open_partition (); 1273 else 1274 # endif /* ! NO_BLOCK_FILES */ 1275 open_device (); 1276 1277 #else /* ! STAGE1_5 */ 1278 1279 if (*filename == '(') 1280 { 1281 if ((filename = set_device (filename)) == 0) 1282 { 1283 current_drive = GRUB_INVALID_DRIVE; 1284 return 0; 1285 } 1286 # ifndef NO_BLOCK_FILES 1287 if (*filename != '/' && current_drive != NETWORK_DRIVE) 1288 open_partition (); 1289 else 1290 # endif /* ! NO_BLOCK_FILES */ 1291 open_device (); 1292 } 1293 else if (saved_drive != current_drive 1294 || saved_partition != current_partition 1295 || (*filename == '/' && fsys_type == NUM_FSYS) 1296 || buf_drive == -1) 1297 { 1298 current_drive = saved_drive; 1299 current_partition = saved_partition; 1300 /* allow for the error case of "no filesystem" after the partition 1301 is found. This makes block files work fine on no filesystem */ 1302 # ifndef NO_BLOCK_FILES 1303 if (*filename != '/' && current_drive != NETWORK_DRIVE) 1304 open_partition (); 1305 else 1306 # endif /* ! NO_BLOCK_FILES */ 1307 open_device (); 1308 } 1309 1310 #endif /* ! STAGE1_5 */ 1311 1312 if (errnum && (*filename == '/' || errnum != ERR_FSYS_MOUNT)) 1313 return 0; 1314 else 1315 errnum = 0; 1316 1317 #ifndef STAGE1_5 1318 if (!sane_partition ()) 1319 return 0; 1320 #endif 1321 1322 return filename; 1323 } 1324 1325 1326 #ifndef STAGE1_5 1327 /* 1328 * This prints the filesystem type or gives relevant information. 1329 */ 1330 1331 void 1332 print_fsys_type (void) 1333 { 1334 if (! do_completion) 1335 { 1336 grub_printf (" Filesystem type "); 1337 1338 if (fsys_type != NUM_FSYS) 1339 grub_printf ("is %s, ", fsys_table[fsys_type].name); 1340 else 1341 grub_printf ("unknown, "); 1342 1343 if (current_partition == 0xFFFFFF) 1344 grub_printf ("using whole disk\n"); 1345 else 1346 grub_printf ("partition type 0x%x\n", current_slice & 0xFF); 1347 } 1348 } 1349 #endif /* STAGE1_5 */ 1350 1351 #ifndef STAGE1_5 1352 /* If DO_COMPLETION is true, just print NAME. Otherwise save the unique 1353 part into UNIQUE_STRING. */ 1354 void 1355 print_a_completion (char *name) 1356 { 1357 /* If NAME is "." or "..", do not count it. */ 1358 if (grub_strcmp (name, ".") == 0 || grub_strcmp (name, "..") == 0) 1359 return; 1360 1361 if (do_completion) 1362 { 1363 char *buf = unique_string; 1364 1365 if (! unique) 1366 while ((*buf++ = *name++)) 1367 ; 1368 else 1369 { 1370 while (*buf && (*buf == *name)) 1371 { 1372 buf++; 1373 name++; 1374 } 1375 /* mismatch, strip it. */ 1376 *buf = '\0'; 1377 } 1378 } 1379 else 1380 grub_printf (" %s", name); 1381 1382 unique++; 1383 } 1384 1385 /* 1386 * This lists the possible completions of a device string, filename, or 1387 * any sane combination of the two. 1388 */ 1389 1390 int 1391 print_completions (int is_filename, int is_completion) 1392 { 1393 char *buf = (char *) COMPLETION_BUF; 1394 char *ptr = buf; 1395 1396 unique_string = (char *) UNIQUE_BUF; 1397 *unique_string = 0; 1398 unique = 0; 1399 do_completion = is_completion; 1400 1401 if (! is_filename) 1402 { 1403 /* Print the completions of builtin commands. */ 1404 struct builtin **builtin; 1405 1406 if (! is_completion) 1407 grub_printf (" Possible commands are:"); 1408 1409 for (builtin = builtin_table; (*builtin); builtin++) 1410 { 1411 /* If *BUILTIN cannot be run in the command-line, skip it. */ 1412 if (! ((*builtin)->flags & BUILTIN_CMDLINE)) 1413 continue; 1414 1415 if (substring (buf, (*builtin)->name) <= 0) 1416 print_a_completion ((*builtin)->name); 1417 } 1418 1419 if (is_completion && *unique_string) 1420 { 1421 if (unique == 1) 1422 { 1423 char *u = unique_string + grub_strlen (unique_string); 1424 1425 *u++ = ' '; 1426 *u = 0; 1427 } 1428 1429 grub_strcpy (buf, unique_string); 1430 } 1431 1432 if (! is_completion) 1433 grub_putchar ('\n'); 1434 1435 print_error (); 1436 do_completion = 0; 1437 if (errnum) 1438 return -1; 1439 else 1440 return unique - 1; 1441 } 1442 1443 if (*buf == '/' || (ptr = set_device (buf)) || incomplete) 1444 { 1445 errnum = 0; 1446 1447 if (*buf == '(' && (incomplete || ! *ptr)) 1448 { 1449 if (! part_choice) 1450 { 1451 /* disk completions */ 1452 int disk_no, i, j; 1453 struct geometry geom; 1454 1455 if (! is_completion) 1456 grub_printf (" Possible disks are: "); 1457 1458 if (!ptr 1459 || *(ptr-1) != 'd' 1460 #ifdef SUPPORT_NETBOOT 1461 || *(ptr-2) != 'n' 1462 #endif /* SUPPORT_NETBOOT */ 1463 || *(ptr-2) != 'c') 1464 { 1465 for (i = (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'h') ? 1:0); 1466 i < (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'f') ? 1:2); 1467 i++) 1468 { 1469 for (j = 0; j < 8; j++) 1470 { 1471 disk_no = (i * 0x80) + j; 1472 if ((disk_choice || disk_no == current_drive) 1473 && ! get_diskinfo (disk_no, &geom)) 1474 { 1475 char dev_name[8]; 1476 1477 grub_sprintf (dev_name, "%cd%d", i ? 'h':'f', j); 1478 print_a_completion (dev_name); 1479 } 1480 } 1481 } 1482 } 1483 1484 if (cdrom_drive != GRUB_INVALID_DRIVE 1485 && (disk_choice || cdrom_drive == current_drive) 1486 && (!ptr 1487 || *(ptr-1) == '(' 1488 || (*(ptr-1) == 'd' && *(ptr-2) == 'c'))) 1489 print_a_completion ("cd"); 1490 1491 # ifdef SUPPORT_NETBOOT 1492 if (network_ready 1493 && (disk_choice || NETWORK_DRIVE == current_drive) 1494 && (!ptr 1495 || *(ptr-1) == '(' 1496 || (*(ptr-1) == 'd' && *(ptr-2) == 'n'))) 1497 print_a_completion ("nd"); 1498 # endif /* SUPPORT_NETBOOT */ 1499 1500 if (is_completion && *unique_string) 1501 { 1502 ptr = buf; 1503 while (*ptr != '(') 1504 ptr--; 1505 ptr++; 1506 grub_strcpy (ptr, unique_string); 1507 if (unique == 1) 1508 { 1509 ptr += grub_strlen (ptr); 1510 if (*unique_string == 'h') 1511 { 1512 *ptr++ = ','; 1513 *ptr = 0; 1514 } 1515 else 1516 { 1517 *ptr++ = ')'; 1518 *ptr = 0; 1519 } 1520 } 1521 } 1522 1523 if (! is_completion) 1524 grub_putchar ('\n'); 1525 } 1526 else 1527 { 1528 /* partition completions */ 1529 if (part_choice == PART_CHOSEN 1530 && open_partition () 1531 && ! IS_PC_SLICE_TYPE_BSD (current_slice)) 1532 { 1533 unique = 1; 1534 ptr = buf + grub_strlen (buf); 1535 if (*(ptr - 1) != ')') 1536 { 1537 *ptr++ = ')'; 1538 *ptr = 0; 1539 } 1540 } 1541 else 1542 { 1543 if (! is_completion) 1544 grub_printf (" Possible partitions are:\n"); 1545 real_open_partition (1); 1546 1547 if (is_completion && *unique_string) 1548 { 1549 ptr = buf; 1550 while (*ptr++ != ',') 1551 ; 1552 grub_strcpy (ptr, unique_string); 1553 } 1554 } 1555 } 1556 } 1557 else if (ptr && *ptr == '/') 1558 { 1559 /* filename completions */ 1560 if (! is_completion) 1561 grub_printf (" Possible files are:"); 1562 1563 dir (buf); 1564 1565 if (is_completion && *unique_string) 1566 { 1567 ptr += grub_strlen (ptr); 1568 while (*ptr != '/') 1569 ptr--; 1570 ptr++; 1571 1572 grub_strcpy (ptr, unique_string); 1573 1574 if (unique == 1) 1575 { 1576 ptr += grub_strlen (unique_string); 1577 1578 /* Check if the file UNIQUE_STRING is a directory. */ 1579 *ptr = '/'; 1580 *(ptr + 1) = 0; 1581 1582 dir (buf); 1583 1584 /* Restore the original unique value. */ 1585 unique = 1; 1586 1587 if (errnum) 1588 { 1589 /* Regular file */ 1590 errnum = 0; 1591 *ptr = ' '; 1592 *(ptr + 1) = 0; 1593 } 1594 } 1595 } 1596 1597 if (! is_completion) 1598 grub_putchar ('\n'); 1599 } 1600 else 1601 errnum = ERR_BAD_FILENAME; 1602 } 1603 1604 print_error (); 1605 do_completion = 0; 1606 if (errnum) 1607 return -1; 1608 else 1609 return unique - 1; 1610 } 1611 #endif /* STAGE1_5 */ 1612 1613 1614 /* 1615 * This is the generic file open function. 1616 */ 1617 1618 int 1619 grub_open (char *filename) 1620 { 1621 #ifndef NO_DECOMPRESSION 1622 compressed_file = 0; 1623 #endif /* NO_DECOMPRESSION */ 1624 1625 /* if any "dir" function uses/sets filepos, it must 1626 set it to zero before returning if opening a file! */ 1627 filepos = 0; 1628 1629 if (!(filename = setup_part (filename))) 1630 return 0; 1631 1632 #ifndef NO_BLOCK_FILES 1633 block_file = 0; 1634 #endif /* NO_BLOCK_FILES */ 1635 1636 /* This accounts for partial filesystem implementations. */ 1637 fsmax = MAXINT; 1638 1639 if (*filename != '/' && current_drive != NETWORK_DRIVE) 1640 { 1641 #ifndef NO_BLOCK_FILES 1642 char *ptr = filename; 1643 int tmp, list_addr = BLK_BLKLIST_START; 1644 filemax = 0; 1645 1646 while (list_addr < BLK_MAX_ADDR) 1647 { 1648 tmp = 0; 1649 safe_parse_maxint (&ptr, &tmp); 1650 errnum = 0; 1651 1652 if (*ptr != '+') 1653 { 1654 if ((*ptr && *ptr != '/' && !isspace (*ptr)) 1655 || tmp == 0 || tmp > filemax) 1656 errnum = ERR_BAD_FILENAME; 1657 else 1658 filemax = tmp; 1659 1660 break; 1661 } 1662 1663 /* since we use the same filesystem buffer, mark it to 1664 be remounted */ 1665 fsys_type = NUM_FSYS; 1666 1667 BLK_BLKSTART (list_addr) = tmp; 1668 ptr++; 1669 1670 if (!safe_parse_maxint (&ptr, &tmp) 1671 || tmp == 0 1672 || (*ptr && *ptr != ',' && *ptr != '/' && !isspace (*ptr))) 1673 { 1674 errnum = ERR_BAD_FILENAME; 1675 break; 1676 } 1677 1678 BLK_BLKLENGTH (list_addr) = tmp; 1679 1680 filemax += (tmp * SECTOR_SIZE); 1681 list_addr += BLK_BLKLIST_INC_VAL; 1682 1683 if (*ptr != ',') 1684 break; 1685 1686 ptr++; 1687 } 1688 1689 if (list_addr < BLK_MAX_ADDR && ptr != filename && !errnum) 1690 { 1691 block_file = 1; 1692 BLK_CUR_FILEPOS = 0; 1693 BLK_CUR_BLKLIST = BLK_BLKLIST_START; 1694 BLK_CUR_BLKNUM = 0; 1695 1696 #ifndef NO_DECOMPRESSION 1697 return gunzip_test_header (); 1698 #else /* NO_DECOMPRESSION */ 1699 return 1; 1700 #endif /* NO_DECOMPRESSION */ 1701 } 1702 #else /* NO_BLOCK_FILES */ 1703 errnum = ERR_BAD_FILENAME; 1704 #endif /* NO_BLOCK_FILES */ 1705 } 1706 1707 if (!errnum && fsys_type == NUM_FSYS) 1708 errnum = ERR_FSYS_MOUNT; 1709 1710 # ifndef STAGE1_5 1711 /* set "dir" function to open a file */ 1712 print_possibilities = 0; 1713 # endif 1714 1715 if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename)) 1716 { 1717 #ifndef NO_DECOMPRESSION 1718 return gunzip_test_header (); 1719 #else /* NO_DECOMPRESSION */ 1720 return 1; 1721 #endif /* NO_DECOMPRESSION */ 1722 } 1723 1724 return 0; 1725 } 1726 1727 1728 int 1729 grub_read (char *buf, int len) 1730 { 1731 /* Make sure "filepos" is a sane value */ 1732 if ((filepos < 0) || (filepos > filemax)) 1733 filepos = filemax; 1734 1735 /* Make sure "len" is a sane value */ 1736 if ((len < 0) || (len > (filemax - filepos))) 1737 len = filemax - filepos; 1738 1739 /* if target file position is past the end of 1740 the supported/configured filesize, then 1741 there is an error */ 1742 if (filepos + len > fsmax) 1743 { 1744 errnum = ERR_FILELENGTH; 1745 return 0; 1746 } 1747 1748 #ifndef NO_DECOMPRESSION 1749 if (compressed_file) 1750 return gunzip_read (buf, len); 1751 #endif /* NO_DECOMPRESSION */ 1752 1753 #ifndef NO_BLOCK_FILES 1754 if (block_file) 1755 { 1756 int size, off, ret = 0; 1757 1758 while (len && !errnum) 1759 { 1760 /* we may need to look for the right block in the list(s) */ 1761 if (filepos < BLK_CUR_FILEPOS) 1762 { 1763 BLK_CUR_FILEPOS = 0; 1764 BLK_CUR_BLKLIST = BLK_BLKLIST_START; 1765 BLK_CUR_BLKNUM = 0; 1766 } 1767 1768 /* run BLK_CUR_FILEPOS up to filepos */ 1769 while (filepos > BLK_CUR_FILEPOS) 1770 { 1771 if ((filepos - (BLK_CUR_FILEPOS & ~(SECTOR_SIZE - 1))) 1772 >= SECTOR_SIZE) 1773 { 1774 BLK_CUR_FILEPOS += SECTOR_SIZE; 1775 BLK_CUR_BLKNUM++; 1776 1777 if (BLK_CUR_BLKNUM >= BLK_BLKLENGTH (BLK_CUR_BLKLIST)) 1778 { 1779 BLK_CUR_BLKLIST += BLK_BLKLIST_INC_VAL; 1780 BLK_CUR_BLKNUM = 0; 1781 } 1782 } 1783 else 1784 BLK_CUR_FILEPOS = filepos; 1785 } 1786 1787 off = filepos & (SECTOR_SIZE - 1); 1788 size = ((BLK_BLKLENGTH (BLK_CUR_BLKLIST) - BLK_CUR_BLKNUM) 1789 * SECTOR_SIZE) - off; 1790 if (size > len) 1791 size = len; 1792 1793 disk_read_func = disk_read_hook; 1794 1795 /* read current block and put it in the right place in memory */ 1796 devread (BLK_BLKSTART (BLK_CUR_BLKLIST) + BLK_CUR_BLKNUM, 1797 off, size, buf); 1798 1799 disk_read_func = NULL; 1800 1801 len -= size; 1802 filepos += size; 1803 ret += size; 1804 buf += size; 1805 } 1806 1807 if (errnum) 1808 ret = 0; 1809 1810 return ret; 1811 } 1812 #endif /* NO_BLOCK_FILES */ 1813 1814 if (fsys_type == NUM_FSYS) 1815 { 1816 errnum = ERR_FSYS_MOUNT; 1817 return 0; 1818 } 1819 1820 return (*(fsys_table[fsys_type].read_func)) (buf, len); 1821 } 1822 1823 #ifndef STAGE1_5 1824 /* Reposition a file offset. */ 1825 int 1826 grub_seek (int offset) 1827 { 1828 if (offset > filemax || offset < 0) 1829 return -1; 1830 1831 filepos = offset; 1832 return offset; 1833 } 1834 1835 int 1836 dir (char *dirname) 1837 { 1838 #ifndef NO_DECOMPRESSION 1839 compressed_file = 0; 1840 #endif /* NO_DECOMPRESSION */ 1841 1842 if (!(dirname = setup_part (dirname))) 1843 return 0; 1844 1845 if (*dirname != '/') 1846 errnum = ERR_BAD_FILENAME; 1847 1848 if (fsys_type == NUM_FSYS) 1849 errnum = ERR_FSYS_MOUNT; 1850 1851 if (errnum) 1852 return 0; 1853 1854 /* set "dir" function to list completions */ 1855 print_possibilities = 1; 1856 1857 return (*(fsys_table[fsys_type].dir_func)) (dirname); 1858 } 1859 #endif /* STAGE1_5 */ 1860 1861 void 1862 grub_close (void) 1863 { 1864 #ifndef NO_BLOCK_FILES 1865 if (block_file) 1866 return; 1867 #endif /* NO_BLOCK_FILES */ 1868 1869 if (fsys_table[fsys_type].close_func != 0) 1870 (*(fsys_table[fsys_type].close_func)) (); 1871 } 1872