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 if ((fsys_table[fsys_type].mount_func) ()) 435 break; 436 437 if (fsys_type == NUM_FSYS && errnum == ERR_NONE) 438 errnum = ERR_FSYS_MOUNT; 439 #else 440 fsys_type = 0; 441 if ((*(fsys_table[fsys_type].mount_func)) () != 1) 442 { 443 fsys_type = NUM_FSYS; 444 errnum = ERR_FSYS_MOUNT; 445 } 446 #endif 447 } 448 449 450 #ifndef STAGE1_5 451 /* Turn on the active flag for the partition SAVED_PARTITION in the 452 drive SAVED_DRIVE. If an error occurs, return zero, otherwise return 453 non-zero. */ 454 int 455 make_saved_active (void) 456 { 457 char mbr[512]; 458 459 if (saved_drive & 0x80) 460 { 461 /* Hard disk */ 462 int part = saved_partition >> 16; 463 464 /* If the partition is not a primary partition, the active flag is 465 meaningless. (XXX: Really?) */ 466 if (part > 3) 467 { 468 errnum = ERR_DEV_VALUES; 469 return 0; 470 } 471 472 /* Read the MBR in the scratch space. */ 473 if (! rawread (saved_drive, 0, 0, SECTOR_SIZE, mbr)) 474 return 0; 475 476 /* If the partition is an extended partition, setting the active 477 flag violates the specification by IBM. */ 478 if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (mbr, part))) 479 { 480 errnum = ERR_DEV_VALUES; 481 return 0; 482 } 483 484 /* Check if the active flag is disabled. */ 485 if (PC_SLICE_FLAG (mbr, part) != PC_SLICE_FLAG_BOOTABLE) 486 { 487 int i; 488 489 /* Clear all the active flags in this table. */ 490 for (i = 0; i < 4; i++) 491 PC_SLICE_FLAG (mbr, i) = 0; 492 493 /* Set the flag. */ 494 PC_SLICE_FLAG (mbr, part) = PC_SLICE_FLAG_BOOTABLE; 495 496 /* Write back the MBR. */ 497 if (! rawwrite (saved_drive, 0, mbr)) 498 return 0; 499 } 500 } 501 else 502 { 503 /* If the drive is not a hard disk drive, you shouldn't call this 504 function. (XXX: Should I just ignore this error?) */ 505 errnum = ERR_DEV_VALUES; 506 return 0; 507 } 508 509 return 1; 510 } 511 512 /* Hide/Unhide CURRENT_PARTITION. */ 513 int 514 set_partition_hidden_flag (int hidden) 515 { 516 unsigned long part = 0xFFFFFF; 517 unsigned long start, len, offset, ext_offset; 518 int entry, type; 519 char mbr[512]; 520 521 /* The drive must be a hard disk. */ 522 if (! (current_drive & 0x80)) 523 { 524 errnum = ERR_BAD_ARGUMENT; 525 return 1; 526 } 527 528 /* The partition must be a PC slice. */ 529 if ((current_partition >> 16) == 0xFF 530 || (current_partition & 0xFFFF) != 0xFFFF) 531 { 532 errnum = ERR_BAD_ARGUMENT; 533 return 1; 534 } 535 536 /* Look for the partition. */ 537 while (next_partition (current_drive, 0xFFFFFF, &part, &type, 538 &start, &len, &offset, &entry, 539 &ext_offset, mbr)) 540 { 541 if (part == current_partition) 542 { 543 /* Found. */ 544 if (hidden) 545 PC_SLICE_TYPE (mbr, entry) |= PC_SLICE_TYPE_HIDDEN_FLAG; 546 else 547 PC_SLICE_TYPE (mbr, entry) &= ~PC_SLICE_TYPE_HIDDEN_FLAG; 548 549 /* Write back the MBR to the disk. */ 550 buf_track = BUF_CACHE_INVALID; 551 if (! rawwrite (current_drive, offset, mbr)) 552 return 1; 553 554 /* Succeed. */ 555 return 0; 556 } 557 } 558 559 return 1; 560 } 561 562 563 static void 564 check_and_print_mount (void) 565 { 566 attempt_mount (); 567 if (errnum == ERR_FSYS_MOUNT) 568 errnum = ERR_NONE; 569 if (!errnum) 570 print_fsys_type (); 571 print_error (); 572 } 573 #endif /* STAGE1_5 */ 574 575 576 /* Get the information on next partition on the drive DRIVE. 577 The caller must not modify the contents of the arguments when 578 iterating this function. The partition representation in GRUB will 579 be stored in *PARTITION. Likewise, the partition type in *TYPE, the 580 start sector in *START, the length in *LEN, the offset of the 581 partition table in *OFFSET, the entry number in the table in *ENTRY, 582 the offset of the extended partition in *EXT_OFFSET. 583 BUF is used to store a MBR, the boot sector of a partition, or 584 a BSD label sector, and it must be at least 512 bytes length. 585 When calling this function first, *PARTITION must be initialized to 586 0xFFFFFF. The return value is zero if fails, otherwise non-zero. */ 587 int 588 next_partition (unsigned long drive, unsigned long dest, 589 unsigned long *partition, int *type, 590 unsigned long *start, unsigned long *len, 591 unsigned long *offset, int *entry, 592 unsigned long *ext_offset, char *buf) 593 { 594 /* Forward declarations. */ 595 auto int next_bsd_partition (void); 596 auto int next_solaris_partition(void); 597 auto int next_pc_slice (void); 598 599 /* Get next BSD partition in current PC slice. */ 600 int next_bsd_partition (void) 601 { 602 int i; 603 int bsd_part_no = (*partition & 0xFF00) >> 8; 604 605 /* If this is the first time... */ 606 if (bsd_part_no == 0xFF) 607 { 608 /* Check if the BSD label is within current PC slice. */ 609 if (*len < BSD_LABEL_SECTOR + 1) 610 { 611 errnum = ERR_BAD_PART_TABLE; 612 return 0; 613 } 614 615 /* Read the BSD label. */ 616 if (! rawread (drive, *start + BSD_LABEL_SECTOR, 617 0, SECTOR_SIZE, buf)) 618 return 0; 619 620 /* Check if it is valid. */ 621 if (! BSD_LABEL_CHECK_MAG (buf)) 622 { 623 errnum = ERR_BAD_PART_TABLE; 624 return 0; 625 } 626 627 bsd_part_no = -1; 628 } 629 630 /* Search next valid BSD partition. */ 631 for (i = bsd_part_no + 1; i < BSD_LABEL_NPARTS (buf); i++) 632 { 633 if (BSD_PART_TYPE (buf, i)) 634 { 635 /* Note that *TYPE and *PARTITION were set 636 for current PC slice. */ 637 *type = (BSD_PART_TYPE (buf, i) << 8) | (*type & 0xFF); 638 *start = BSD_PART_START (buf, i); 639 *len = BSD_PART_LENGTH (buf, i); 640 *partition = (*partition & 0xFF00FF) | (i << 8); 641 642 #ifndef STAGE1_5 643 /* XXX */ 644 if ((drive & 0x80) && BSD_LABEL_DTYPE (buf) == DTYPE_SCSI) 645 bsd_evil_hack = 4; 646 #endif /* ! STAGE1_5 */ 647 648 return 1; 649 } 650 } 651 652 errnum = ERR_NO_PART; 653 return 0; 654 } 655 656 /* Get next Solaris partition in current PC slice. */ 657 int next_solaris_partition (void) 658 { 659 static unsigned long pcs_start; 660 int i; 661 int sol_part_no = (*partition & 0xFF00) >> 8; 662 663 /* If this is the first time... */ 664 if (sol_part_no == 0xFF) 665 { 666 /* Check if the Solaris label is within current PC slice. */ 667 if (*len < SOL_LABEL_LOC + 1) 668 { 669 errnum = ERR_BAD_PART_TABLE; 670 return 0; 671 } 672 673 /* Read the Solaris label. */ 674 if (! rawread (drive, *start + SOL_LABEL_LOC, 0, SECTOR_SIZE, buf)) 675 return 0; 676 677 /* Check if it is valid. */ 678 if (! SOL_LABEL_CHECK_MAG (buf)) 679 { 680 errnum = ERR_BAD_PART_TABLE; 681 return 0; 682 } 683 684 sol_part_no = -1; 685 pcs_start = *start; /* save the start of pc slice */ 686 } 687 688 /* Search next valid Solaris partition. */ 689 for (i = sol_part_no + 1; i < SOL_LABEL_NPARTS; i++) 690 { 691 if (SOL_PART_EXISTS (buf, i)) 692 { 693 /* SOL_PART_START is relative to fdisk partition */ 694 *start = SOL_PART_START (buf, i) + pcs_start; 695 *len = SOL_PART_LENGTH (buf, i); 696 *partition = (*partition & 0xFF00FF) | (i << 8); 697 698 return 1; 699 } 700 } 701 702 errnum = ERR_NO_PART; 703 return 0; 704 } 705 706 /* Get next PC slice. Be careful of that this function may return 707 an empty PC slice (i.e. a partition whose type is zero) as well. */ 708 int next_pc_slice (void) 709 { 710 int pc_slice_no = (*partition & 0xFF0000) >> 16; 711 712 /* If this is the first time... */ 713 if (pc_slice_no == 0xFF) 714 { 715 *offset = 0; 716 *ext_offset = 0; 717 *entry = -1; 718 pc_slice_no = -1; 719 } 720 721 /* Read the MBR or the boot sector of the extended partition. */ 722 if (! rawread (drive, *offset, 0, SECTOR_SIZE, buf)) 723 return 0; 724 725 /* Check if it is valid. */ 726 if (! PC_MBR_CHECK_SIG (buf)) 727 { 728 errnum = ERR_BAD_PART_TABLE; 729 return 0; 730 } 731 732 /* Increase the entry number. */ 733 (*entry)++; 734 735 /* If this is out of current partition table... */ 736 if (*entry == PC_SLICE_MAX) 737 { 738 int i; 739 740 /* Search the first extended partition in current table. */ 741 for (i = 0; i < PC_SLICE_MAX; i++) 742 { 743 if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (buf, i))) 744 { 745 /* Found. Set the new offset and the entry number, 746 and restart this function. */ 747 *offset = *ext_offset + PC_SLICE_START (buf, i); 748 if (! *ext_offset) 749 *ext_offset = *offset; 750 *entry = -1; 751 return next_pc_slice (); 752 } 753 } 754 755 errnum = ERR_NO_PART; 756 return 0; 757 } 758 759 *type = PC_SLICE_TYPE (buf, *entry); 760 *start = *offset + PC_SLICE_START (buf, *entry); 761 *len = PC_SLICE_LENGTH (buf, *entry); 762 763 /* The calculation of a PC slice number is complicated, because of 764 the rather odd definition of extended partitions. Even worse, 765 there is no guarantee that this is consistent with every 766 operating systems. Uggh. */ 767 if (pc_slice_no < PC_SLICE_MAX 768 || (! IS_PC_SLICE_TYPE_EXTENDED (*type) 769 && *type != PC_SLICE_TYPE_NONE)) 770 pc_slice_no++; 771 772 *partition = (pc_slice_no << 16) | 0xFFFF; 773 return 1; 774 } 775 776 /* Start the body of this function. */ 777 778 #ifndef STAGE1_5 779 if (current_drive == NETWORK_DRIVE) 780 return 0; 781 #endif 782 783 /* check for Solaris partition */ 784 if (*partition != 0xFFFFFF && IS_PC_SLICE_TYPE_SOLARIS (*type & 0xff)) 785 { 786 if (next_solaris_partition ()) 787 return 1; 788 errnum = ERR_NONE; 789 } 790 791 /* If previous partition is a BSD partition or a PC slice which 792 contains BSD partitions... */ 793 if ((*partition != 0xFFFFFF && IS_PC_SLICE_TYPE_BSD (*type & 0xff)) 794 || ! (drive & 0x80)) 795 { 796 if (*type == PC_SLICE_TYPE_NONE) 797 *type = PC_SLICE_TYPE_FREEBSD; 798 799 /* Get next BSD partition, if any. */ 800 if (next_bsd_partition ()) 801 return 1; 802 803 /* If the destination partition is a BSD partition and current 804 BSD partition has any error, abort the operation. */ 805 if ((dest & 0xFF00) != 0xFF00 806 && ((dest & 0xFF0000) == 0xFF0000 807 || (dest & 0xFF0000) == (*partition & 0xFF0000))) 808 return 0; 809 810 /* Ignore the error. */ 811 errnum = ERR_NONE; 812 } 813 814 return next_pc_slice (); 815 } 816 817 #ifndef STAGE1_5 818 static unsigned long cur_part_offset; 819 static unsigned long cur_part_addr; 820 #endif 821 822 /* Open a partition. */ 823 int 824 real_open_partition (int flags) 825 { 826 unsigned long dest_partition = current_partition; 827 unsigned long part_offset; 828 unsigned long ext_offset; 829 int entry; 830 char buf[SECTOR_SIZE]; 831 int unix_part, pc_slice; 832 833 /* For simplicity. */ 834 auto int next (void); 835 int next (void) 836 { 837 int ret = next_partition (current_drive, dest_partition, 838 ¤t_partition, ¤t_slice, 839 &part_start, &part_length, 840 &part_offset, &entry, &ext_offset, buf); 841 unix_part = (current_partition >> 8) & 0xFF; 842 pc_slice = current_partition >> 16; 843 return ret; 844 } 845 846 #ifndef STAGE1_5 847 /* network drive */ 848 if (current_drive == NETWORK_DRIVE) 849 return 1; 850 851 if (! sane_partition ()) 852 return 0; 853 #endif 854 855 bsd_evil_hack = 0; 856 current_slice = 0; 857 part_start = 0; 858 859 /* Make sure that buf_geom is valid. */ 860 if (buf_drive != current_drive) 861 { 862 if (get_diskinfo (current_drive, &buf_geom)) 863 { 864 errnum = ERR_NO_DISK; 865 return 0; 866 } 867 buf_drive = current_drive; 868 buf_track = BUF_CACHE_INVALID; 869 } 870 part_length = 871 (buf_geom.total_sectors > MAXUINT) ? MAXUINT : buf_geom.total_sectors; 872 873 /* If this is the whole disk, return here. */ 874 if (! flags && current_partition == 0xFFFFFF) 875 return 1; 876 877 if (flags) 878 dest_partition = 0xFFFFFF; 879 880 /* Initialize CURRENT_PARTITION for next_partition. */ 881 current_partition = 0xFFFFFF; 882 883 while (next ()) 884 { 885 #ifndef STAGE1_5 886 loop_start: 887 888 cur_part_offset = part_offset; 889 cur_part_addr = BOOT_PART_TABLE + (entry << 4); 890 #endif /* ! STAGE1_5 */ 891 892 /* If this is a valid partition... */ 893 if (current_slice) 894 { 895 #ifndef STAGE1_5 896 /* Display partition information. */ 897 if (flags && ! IS_PC_SLICE_TYPE_EXTENDED (current_slice)) 898 { 899 if (! do_completion) 900 { 901 if (current_drive & 0x80) 902 grub_printf (" Partition num: %d, ", 903 current_partition >> 16); 904 905 if (! IS_PC_SLICE_TYPE_BSD (current_slice) && 906 ! IS_PC_SLICE_TYPE_SOLARIS (current_slice)) 907 check_and_print_mount (); 908 else 909 { 910 int got_part = 0; 911 int saved_slice = current_slice; 912 913 while (next ()) 914 { 915 if (unix_part == 0xFF) 916 break; 917 918 if (! got_part) 919 { 920 grub_printf ("[BSD/SOLARIS sub-partitions immediately follow]\n"); 921 got_part = 1; 922 } 923 924 grub_printf (" BSD/SOLARIS Partition num: \'%c\', ", 925 unix_part + 'a'); 926 check_and_print_mount (); 927 } 928 929 if (! got_part) 930 grub_printf (" No BSD/SOLARIS sub-partition found, partition type 0x%x\n", 931 saved_slice); 932 933 if (errnum) 934 { 935 errnum = ERR_NONE; 936 break; 937 } 938 939 goto loop_start; 940 } 941 } 942 else 943 { 944 if (unix_part != 0xFF) 945 { 946 char str[16]; 947 948 if (! (current_drive & 0x80) 949 || (dest_partition >> 16) == pc_slice) 950 grub_sprintf (str, "%c)", unix_part + 'a'); 951 else 952 grub_sprintf (str, "%d,%c)", 953 pc_slice, unix_part + 'a'); 954 print_a_completion (str); 955 } 956 else if (! IS_PC_SLICE_TYPE_BSD (current_slice) && 957 ! IS_PC_SLICE_TYPE_SOLARIS (current_slice)) 958 { 959 char str[8]; 960 961 grub_sprintf (str, "%d)", pc_slice); 962 print_a_completion (str); 963 } 964 } 965 } 966 967 errnum = ERR_NONE; 968 #endif /* ! STAGE1_5 */ 969 970 /* Check if this is the destination partition. */ 971 if (! flags 972 && (dest_partition == current_partition 973 || ((dest_partition >> 16) == 0xFF 974 && ((dest_partition >> 8) & 0xFF) == unix_part))) 975 return 1; 976 } 977 } 978 979 #ifndef STAGE1_5 980 if (flags) 981 { 982 if (! (current_drive & 0x80)) 983 { 984 current_partition = 0xFFFFFF; 985 check_and_print_mount (); 986 } 987 988 errnum = ERR_NONE; 989 return 1; 990 } 991 #endif /* ! STAGE1_5 */ 992 993 return 0; 994 } 995 996 997 int 998 open_partition (void) 999 { 1000 return real_open_partition (0); 1001 } 1002 1003 1004 #ifndef STAGE1_5 1005 /* XX used for device completion in 'set_device' and 'print_completions' */ 1006 static int incomplete, disk_choice; 1007 static enum 1008 { 1009 PART_UNSPECIFIED = 0, 1010 PART_DISK, 1011 PART_CHOSEN, 1012 } 1013 part_choice; 1014 #endif /* ! STAGE1_5 */ 1015 1016 char * 1017 set_device (char *device) 1018 { 1019 #ifdef STAGE1_5 1020 /* In Stage 1.5, the first 4 bytes of FILENAME has a device number. */ 1021 unsigned long dev = *((unsigned long *) device); 1022 int drive = (dev >> 24) & 0xFF; 1023 int partition = dev & 0xFFFFFF; 1024 1025 /* If DRIVE is disabled, use SAVED_DRIVE instead. */ 1026 if (drive == GRUB_INVALID_DRIVE) 1027 current_drive = saved_drive; 1028 else 1029 current_drive = drive; 1030 1031 /* The `partition' part must always have a valid number. */ 1032 current_partition = partition; 1033 1034 return device + sizeof (unsigned long); 1035 1036 #else /* ! STAGE1_5 */ 1037 1038 int result = 0; 1039 1040 incomplete = 0; 1041 disk_choice = 1; 1042 part_choice = PART_UNSPECIFIED; 1043 current_drive = saved_drive; 1044 current_partition = 0xFFFFFF; 1045 1046 if (*device == '(' && !*(device + 1)) 1047 /* user has given '(' only, let disk_choice handle what disks we have */ 1048 return device + 1; 1049 1050 if (*device == '(' && *(++device)) 1051 { 1052 if (*device != ',' && *device != ')') 1053 { 1054 char ch = *device; 1055 #ifdef SUPPORT_NETBOOT 1056 if (*device == 'f' || *device == 'h' 1057 || (*device == 'n' && network_ready) 1058 || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE)) 1059 #else 1060 if (*device == 'f' || *device == 'h' 1061 || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE)) 1062 #endif /* SUPPORT_NETBOOT */ 1063 { 1064 /* user has given '([fhn]', check for resp. add 'd' and 1065 let disk_choice handle what disks we have */ 1066 if (!*(device + 1)) 1067 { 1068 device++; 1069 *device++ = 'd'; 1070 *device = '\0'; 1071 return device; 1072 } 1073 else if (*(device + 1) == 'd' && !*(device + 2)) 1074 return device + 2; 1075 } 1076 1077 if ((*device == 'f' 1078 || *device == 'h' 1079 #ifdef SUPPORT_NETBOOT 1080 || (*device == 'n' && network_ready) 1081 #endif 1082 || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE)) 1083 && (device += 2, (*(device - 1) != 'd'))) 1084 errnum = ERR_NUMBER_PARSING; 1085 1086 #ifdef SUPPORT_NETBOOT 1087 if (ch == 'n' && network_ready) 1088 current_drive = NETWORK_DRIVE; 1089 else 1090 #endif /* SUPPORT_NETBOOT */ 1091 { 1092 if (ch == 'c' && cdrom_drive != GRUB_INVALID_DRIVE) 1093 current_drive = cdrom_drive; 1094 else 1095 { 1096 safe_parse_maxint (&device, (int *) ¤t_drive); 1097 1098 disk_choice = 0; 1099 if (ch == 'h') 1100 current_drive += 0x80; 1101 } 1102 } 1103 } 1104 1105 if (errnum) 1106 return 0; 1107 1108 if (*device == ')') 1109 { 1110 part_choice = PART_CHOSEN; 1111 result = 1; 1112 } 1113 else if (*device == ',') 1114 { 1115 /* Either an absolute PC, BSD, or Solaris partition. */ 1116 disk_choice = 0; 1117 part_choice ++; 1118 device++; 1119 1120 if (*device >= '0' && *device <= '9') 1121 { 1122 part_choice ++; 1123 current_partition = 0; 1124 1125 if (!(current_drive & 0x80) 1126 || !safe_parse_maxint (&device, (int *) ¤t_partition) 1127 || current_partition > 254) 1128 { 1129 errnum = ERR_DEV_FORMAT; 1130 return 0; 1131 } 1132 1133 current_partition = (current_partition << 16) + 0xFFFF; 1134 1135 if (*device == ',') 1136 device++; 1137 1138 if (*device >= 'a' && *device <= 'p') 1139 { 1140 current_partition = (((*(device++) - 'a') << 8) 1141 | (current_partition & 0xFF00FF)); 1142 } 1143 } 1144 else if (*device >= 'a' && *device <= 'p') 1145 { 1146 part_choice ++; 1147 current_partition = ((*(device++) - 'a') << 8) | 0xFF00FF; 1148 } 1149 1150 if (*device == ')') 1151 { 1152 if (part_choice == PART_DISK) 1153 { 1154 current_partition = saved_partition; 1155 part_choice ++; 1156 } 1157 1158 result = 1; 1159 } 1160 } 1161 } 1162 1163 if (! sane_partition ()) 1164 return 0; 1165 1166 if (result) 1167 return device + 1; 1168 else 1169 { 1170 if (!*device) 1171 incomplete = 1; 1172 errnum = ERR_DEV_FORMAT; 1173 } 1174 1175 return 0; 1176 1177 #endif /* ! STAGE1_5 */ 1178 } 1179 1180 /* 1181 * This performs a "mount" on the current device, both drive and partition 1182 * number. 1183 */ 1184 1185 int 1186 open_device (void) 1187 { 1188 if (open_partition ()) 1189 attempt_mount (); 1190 1191 if (errnum != ERR_NONE) 1192 return 0; 1193 1194 return 1; 1195 } 1196 1197 1198 #ifndef STAGE1_5 1199 int 1200 set_bootdev (int hdbias) 1201 { 1202 int i, j; 1203 1204 /* Copy the boot partition information to 0x7be-0x7fd for chain-loading. */ 1205 if ((saved_drive & 0x80) && cur_part_addr) 1206 { 1207 if (rawread (saved_drive, cur_part_offset, 1208 0, SECTOR_SIZE, (char *) SCRATCHADDR)) 1209 { 1210 char *dst, *src; 1211 1212 /* Need only the partition table. 1213 XXX: We cannot use grub_memmove because BOOT_PART_TABLE 1214 (0x07be) is less than 0x1000. */ 1215 dst = (char *) BOOT_PART_TABLE; 1216 src = (char *) SCRATCHADDR + BOOTSEC_PART_OFFSET; 1217 while (dst < (char *) BOOT_PART_TABLE + BOOTSEC_PART_LENGTH) 1218 *dst++ = *src++; 1219 1220 /* Set the active flag of the booted partition. */ 1221 for (i = 0; i < 4; i++) 1222 PC_SLICE_FLAG (BOOT_PART_TABLE, i) = 0; 1223 1224 *((unsigned char *) cur_part_addr) = PC_SLICE_FLAG_BOOTABLE; 1225 boot_part_addr = cur_part_addr; 1226 } 1227 else 1228 return 0; 1229 } 1230 1231 /* 1232 * Set BSD boot device. 1233 */ 1234 i = (saved_partition >> 16) + 2; 1235 if (saved_partition == 0xFFFFFF) 1236 i = 1; 1237 else if ((saved_partition >> 16) == 0xFF) 1238 i = 0; 1239 1240 /* FIXME: extremely evil hack!!! */ 1241 j = 2; 1242 if (saved_drive & 0x80) 1243 j = bsd_evil_hack; 1244 1245 return MAKEBOOTDEV (j, (i >> 4), (i & 0xF), 1246 ((saved_drive - hdbias) & 0x7F), 1247 ((saved_partition >> 8) & 0xFF)); 1248 } 1249 #endif /* STAGE1_5 */ 1250 1251 1252 static char * 1253 setup_part (char *filename) 1254 { 1255 #ifdef STAGE1_5 1256 1257 if (! (filename = set_device (filename))) 1258 { 1259 current_drive = GRUB_INVALID_DRIVE; 1260 return 0; 1261 } 1262 1263 # ifndef NO_BLOCK_FILES 1264 if (*filename != '/') 1265 open_partition (); 1266 else 1267 # endif /* ! NO_BLOCK_FILES */ 1268 open_device (); 1269 1270 #else /* ! STAGE1_5 */ 1271 1272 if (*filename == '(') 1273 { 1274 if ((filename = set_device (filename)) == 0) 1275 { 1276 current_drive = GRUB_INVALID_DRIVE; 1277 return 0; 1278 } 1279 # ifndef NO_BLOCK_FILES 1280 if (*filename != '/' && current_drive != NETWORK_DRIVE) 1281 open_partition (); 1282 else 1283 # endif /* ! NO_BLOCK_FILES */ 1284 open_device (); 1285 } 1286 else if (saved_drive != current_drive 1287 || saved_partition != current_partition 1288 || (*filename == '/' && fsys_type == NUM_FSYS) 1289 || buf_drive == -1) 1290 { 1291 current_drive = saved_drive; 1292 current_partition = saved_partition; 1293 /* allow for the error case of "no filesystem" after the partition 1294 is found. This makes block files work fine on no filesystem */ 1295 # ifndef NO_BLOCK_FILES 1296 if (*filename != '/' && current_drive != NETWORK_DRIVE) 1297 open_partition (); 1298 else 1299 # endif /* ! NO_BLOCK_FILES */ 1300 open_device (); 1301 } 1302 1303 #endif /* ! STAGE1_5 */ 1304 1305 if (errnum && (*filename == '/' || errnum != ERR_FSYS_MOUNT)) 1306 return 0; 1307 else 1308 errnum = 0; 1309 1310 #ifndef STAGE1_5 1311 if (!sane_partition ()) 1312 return 0; 1313 #endif 1314 1315 return filename; 1316 } 1317 1318 1319 #ifndef STAGE1_5 1320 /* 1321 * This prints the filesystem type or gives relevant information. 1322 */ 1323 1324 void 1325 print_fsys_type (void) 1326 { 1327 if (! do_completion) 1328 { 1329 grub_printf (" Filesystem type "); 1330 1331 if (fsys_type != NUM_FSYS) 1332 grub_printf ("is %s, ", fsys_table[fsys_type].name); 1333 else 1334 grub_printf ("unknown, "); 1335 1336 if (current_partition == 0xFFFFFF) 1337 grub_printf ("using whole disk\n"); 1338 else 1339 grub_printf ("partition type 0x%x\n", current_slice & 0xFF); 1340 } 1341 } 1342 #endif /* STAGE1_5 */ 1343 1344 #ifndef STAGE1_5 1345 /* If DO_COMPLETION is true, just print NAME. Otherwise save the unique 1346 part into UNIQUE_STRING. */ 1347 void 1348 print_a_completion (char *name) 1349 { 1350 /* If NAME is "." or "..", do not count it. */ 1351 if (grub_strcmp (name, ".") == 0 || grub_strcmp (name, "..") == 0) 1352 return; 1353 1354 if (do_completion) 1355 { 1356 char *buf = unique_string; 1357 1358 if (! unique) 1359 while ((*buf++ = *name++)) 1360 ; 1361 else 1362 { 1363 while (*buf && (*buf == *name)) 1364 { 1365 buf++; 1366 name++; 1367 } 1368 /* mismatch, strip it. */ 1369 *buf = '\0'; 1370 } 1371 } 1372 else 1373 grub_printf (" %s", name); 1374 1375 unique++; 1376 } 1377 1378 /* 1379 * This lists the possible completions of a device string, filename, or 1380 * any sane combination of the two. 1381 */ 1382 1383 int 1384 print_completions (int is_filename, int is_completion) 1385 { 1386 char *buf = (char *) COMPLETION_BUF; 1387 char *ptr = buf; 1388 1389 unique_string = (char *) UNIQUE_BUF; 1390 *unique_string = 0; 1391 unique = 0; 1392 do_completion = is_completion; 1393 1394 if (! is_filename) 1395 { 1396 /* Print the completions of builtin commands. */ 1397 struct builtin **builtin; 1398 1399 if (! is_completion) 1400 grub_printf (" Possible commands are:"); 1401 1402 for (builtin = builtin_table; (*builtin); builtin++) 1403 { 1404 /* If *BUILTIN cannot be run in the command-line, skip it. */ 1405 if (! ((*builtin)->flags & BUILTIN_CMDLINE)) 1406 continue; 1407 1408 if (substring (buf, (*builtin)->name) <= 0) 1409 print_a_completion ((*builtin)->name); 1410 } 1411 1412 if (is_completion && *unique_string) 1413 { 1414 if (unique == 1) 1415 { 1416 char *u = unique_string + grub_strlen (unique_string); 1417 1418 *u++ = ' '; 1419 *u = 0; 1420 } 1421 1422 grub_strcpy (buf, unique_string); 1423 } 1424 1425 if (! is_completion) 1426 grub_putchar ('\n'); 1427 1428 print_error (); 1429 do_completion = 0; 1430 if (errnum) 1431 return -1; 1432 else 1433 return unique - 1; 1434 } 1435 1436 if (*buf == '/' || (ptr = set_device (buf)) || incomplete) 1437 { 1438 errnum = 0; 1439 1440 if (*buf == '(' && (incomplete || ! *ptr)) 1441 { 1442 if (! part_choice) 1443 { 1444 /* disk completions */ 1445 int disk_no, i, j; 1446 struct geometry geom; 1447 1448 if (! is_completion) 1449 grub_printf (" Possible disks are: "); 1450 1451 if (!ptr 1452 || *(ptr-1) != 'd' 1453 #ifdef SUPPORT_NETBOOT 1454 || *(ptr-2) != 'n' 1455 #endif /* SUPPORT_NETBOOT */ 1456 || *(ptr-2) != 'c') 1457 { 1458 for (i = (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'h') ? 1:0); 1459 i < (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'f') ? 1:2); 1460 i++) 1461 { 1462 for (j = 0; j < 8; j++) 1463 { 1464 disk_no = (i * 0x80) + j; 1465 if ((disk_choice || disk_no == current_drive) 1466 && ! get_diskinfo (disk_no, &geom)) 1467 { 1468 char dev_name[8]; 1469 1470 grub_sprintf (dev_name, "%cd%d", i ? 'h':'f', j); 1471 print_a_completion (dev_name); 1472 } 1473 } 1474 } 1475 } 1476 1477 if (cdrom_drive != GRUB_INVALID_DRIVE 1478 && (disk_choice || cdrom_drive == current_drive) 1479 && (!ptr 1480 || *(ptr-1) == '(' 1481 || (*(ptr-1) == 'd' && *(ptr-2) == 'c'))) 1482 print_a_completion ("cd"); 1483 1484 # ifdef SUPPORT_NETBOOT 1485 if (network_ready 1486 && (disk_choice || NETWORK_DRIVE == current_drive) 1487 && (!ptr 1488 || *(ptr-1) == '(' 1489 || (*(ptr-1) == 'd' && *(ptr-2) == 'n'))) 1490 print_a_completion ("nd"); 1491 # endif /* SUPPORT_NETBOOT */ 1492 1493 if (is_completion && *unique_string) 1494 { 1495 ptr = buf; 1496 while (*ptr != '(') 1497 ptr--; 1498 ptr++; 1499 grub_strcpy (ptr, unique_string); 1500 if (unique == 1) 1501 { 1502 ptr += grub_strlen (ptr); 1503 if (*unique_string == 'h') 1504 { 1505 *ptr++ = ','; 1506 *ptr = 0; 1507 } 1508 else 1509 { 1510 *ptr++ = ')'; 1511 *ptr = 0; 1512 } 1513 } 1514 } 1515 1516 if (! is_completion) 1517 grub_putchar ('\n'); 1518 } 1519 else 1520 { 1521 /* partition completions */ 1522 if (part_choice == PART_CHOSEN 1523 && open_partition () 1524 && ! IS_PC_SLICE_TYPE_BSD (current_slice)) 1525 { 1526 unique = 1; 1527 ptr = buf + grub_strlen (buf); 1528 if (*(ptr - 1) != ')') 1529 { 1530 *ptr++ = ')'; 1531 *ptr = 0; 1532 } 1533 } 1534 else 1535 { 1536 if (! is_completion) 1537 grub_printf (" Possible partitions are:\n"); 1538 real_open_partition (1); 1539 1540 if (is_completion && *unique_string) 1541 { 1542 ptr = buf; 1543 while (*ptr++ != ',') 1544 ; 1545 grub_strcpy (ptr, unique_string); 1546 } 1547 } 1548 } 1549 } 1550 else if (ptr && *ptr == '/') 1551 { 1552 /* filename completions */ 1553 if (! is_completion) 1554 grub_printf (" Possible files are:"); 1555 1556 dir (buf); 1557 1558 if (is_completion && *unique_string) 1559 { 1560 ptr += grub_strlen (ptr); 1561 while (*ptr != '/') 1562 ptr--; 1563 ptr++; 1564 1565 grub_strcpy (ptr, unique_string); 1566 1567 if (unique == 1) 1568 { 1569 ptr += grub_strlen (unique_string); 1570 1571 /* Check if the file UNIQUE_STRING is a directory. */ 1572 *ptr = '/'; 1573 *(ptr + 1) = 0; 1574 1575 dir (buf); 1576 1577 /* Restore the original unique value. */ 1578 unique = 1; 1579 1580 if (errnum) 1581 { 1582 /* Regular file */ 1583 errnum = 0; 1584 *ptr = ' '; 1585 *(ptr + 1) = 0; 1586 } 1587 } 1588 } 1589 1590 if (! is_completion) 1591 grub_putchar ('\n'); 1592 } 1593 else 1594 errnum = ERR_BAD_FILENAME; 1595 } 1596 1597 print_error (); 1598 do_completion = 0; 1599 if (errnum) 1600 return -1; 1601 else 1602 return unique - 1; 1603 } 1604 #endif /* STAGE1_5 */ 1605 1606 1607 /* 1608 * This is the generic file open function. 1609 */ 1610 1611 int 1612 grub_open (char *filename) 1613 { 1614 #ifndef NO_DECOMPRESSION 1615 compressed_file = 0; 1616 #endif /* NO_DECOMPRESSION */ 1617 1618 /* if any "dir" function uses/sets filepos, it must 1619 set it to zero before returning if opening a file! */ 1620 filepos = 0; 1621 1622 if (!(filename = setup_part (filename))) 1623 return 0; 1624 1625 #ifndef NO_BLOCK_FILES 1626 block_file = 0; 1627 #endif /* NO_BLOCK_FILES */ 1628 1629 /* This accounts for partial filesystem implementations. */ 1630 fsmax = MAXINT; 1631 1632 if (*filename != '/' && current_drive != NETWORK_DRIVE) 1633 { 1634 #ifndef NO_BLOCK_FILES 1635 char *ptr = filename; 1636 int tmp, list_addr = BLK_BLKLIST_START; 1637 filemax = 0; 1638 1639 while (list_addr < BLK_MAX_ADDR) 1640 { 1641 tmp = 0; 1642 safe_parse_maxint (&ptr, &tmp); 1643 errnum = 0; 1644 1645 if (*ptr != '+') 1646 { 1647 if ((*ptr && *ptr != '/' && !isspace (*ptr)) 1648 || tmp == 0 || tmp > filemax) 1649 errnum = ERR_BAD_FILENAME; 1650 else 1651 filemax = tmp; 1652 1653 break; 1654 } 1655 1656 /* since we use the same filesystem buffer, mark it to 1657 be remounted */ 1658 fsys_type = NUM_FSYS; 1659 1660 BLK_BLKSTART (list_addr) = tmp; 1661 ptr++; 1662 1663 if (!safe_parse_maxint (&ptr, &tmp) 1664 || tmp == 0 1665 || (*ptr && *ptr != ',' && *ptr != '/' && !isspace (*ptr))) 1666 { 1667 errnum = ERR_BAD_FILENAME; 1668 break; 1669 } 1670 1671 BLK_BLKLENGTH (list_addr) = tmp; 1672 1673 filemax += (tmp * SECTOR_SIZE); 1674 list_addr += BLK_BLKLIST_INC_VAL; 1675 1676 if (*ptr != ',') 1677 break; 1678 1679 ptr++; 1680 } 1681 1682 if (list_addr < BLK_MAX_ADDR && ptr != filename && !errnum) 1683 { 1684 block_file = 1; 1685 BLK_CUR_FILEPOS = 0; 1686 BLK_CUR_BLKLIST = BLK_BLKLIST_START; 1687 BLK_CUR_BLKNUM = 0; 1688 1689 #ifndef NO_DECOMPRESSION 1690 return gunzip_test_header (); 1691 #else /* NO_DECOMPRESSION */ 1692 return 1; 1693 #endif /* NO_DECOMPRESSION */ 1694 } 1695 #else /* NO_BLOCK_FILES */ 1696 errnum = ERR_BAD_FILENAME; 1697 #endif /* NO_BLOCK_FILES */ 1698 } 1699 1700 if (!errnum && fsys_type == NUM_FSYS) 1701 errnum = ERR_FSYS_MOUNT; 1702 1703 # ifndef STAGE1_5 1704 /* set "dir" function to open a file */ 1705 print_possibilities = 0; 1706 # endif 1707 1708 if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename)) 1709 { 1710 #ifndef NO_DECOMPRESSION 1711 return gunzip_test_header (); 1712 #else /* NO_DECOMPRESSION */ 1713 return 1; 1714 #endif /* NO_DECOMPRESSION */ 1715 } 1716 1717 return 0; 1718 } 1719 1720 1721 int 1722 grub_read (char *buf, int len) 1723 { 1724 /* Make sure "filepos" is a sane value */ 1725 if ((filepos < 0) || (filepos > filemax)) 1726 filepos = filemax; 1727 1728 /* Make sure "len" is a sane value */ 1729 if ((len < 0) || (len > (filemax - filepos))) 1730 len = filemax - filepos; 1731 1732 /* if target file position is past the end of 1733 the supported/configured filesize, then 1734 there is an error */ 1735 if (filepos + len > fsmax) 1736 { 1737 errnum = ERR_FILELENGTH; 1738 return 0; 1739 } 1740 1741 #ifndef NO_DECOMPRESSION 1742 if (compressed_file) 1743 return gunzip_read (buf, len); 1744 #endif /* NO_DECOMPRESSION */ 1745 1746 #ifndef NO_BLOCK_FILES 1747 if (block_file) 1748 { 1749 int size, off, ret = 0; 1750 1751 while (len && !errnum) 1752 { 1753 /* we may need to look for the right block in the list(s) */ 1754 if (filepos < BLK_CUR_FILEPOS) 1755 { 1756 BLK_CUR_FILEPOS = 0; 1757 BLK_CUR_BLKLIST = BLK_BLKLIST_START; 1758 BLK_CUR_BLKNUM = 0; 1759 } 1760 1761 /* run BLK_CUR_FILEPOS up to filepos */ 1762 while (filepos > BLK_CUR_FILEPOS) 1763 { 1764 if ((filepos - (BLK_CUR_FILEPOS & ~(SECTOR_SIZE - 1))) 1765 >= SECTOR_SIZE) 1766 { 1767 BLK_CUR_FILEPOS += SECTOR_SIZE; 1768 BLK_CUR_BLKNUM++; 1769 1770 if (BLK_CUR_BLKNUM >= BLK_BLKLENGTH (BLK_CUR_BLKLIST)) 1771 { 1772 BLK_CUR_BLKLIST += BLK_BLKLIST_INC_VAL; 1773 BLK_CUR_BLKNUM = 0; 1774 } 1775 } 1776 else 1777 BLK_CUR_FILEPOS = filepos; 1778 } 1779 1780 off = filepos & (SECTOR_SIZE - 1); 1781 size = ((BLK_BLKLENGTH (BLK_CUR_BLKLIST) - BLK_CUR_BLKNUM) 1782 * SECTOR_SIZE) - off; 1783 if (size > len) 1784 size = len; 1785 1786 disk_read_func = disk_read_hook; 1787 1788 /* read current block and put it in the right place in memory */ 1789 devread (BLK_BLKSTART (BLK_CUR_BLKLIST) + BLK_CUR_BLKNUM, 1790 off, size, buf); 1791 1792 disk_read_func = NULL; 1793 1794 len -= size; 1795 filepos += size; 1796 ret += size; 1797 buf += size; 1798 } 1799 1800 if (errnum) 1801 ret = 0; 1802 1803 return ret; 1804 } 1805 #endif /* NO_BLOCK_FILES */ 1806 1807 if (fsys_type == NUM_FSYS) 1808 { 1809 errnum = ERR_FSYS_MOUNT; 1810 return 0; 1811 } 1812 1813 return (*(fsys_table[fsys_type].read_func)) (buf, len); 1814 } 1815 1816 #ifndef STAGE1_5 1817 /* Reposition a file offset. */ 1818 int 1819 grub_seek (int offset) 1820 { 1821 if (offset > filemax || offset < 0) 1822 return -1; 1823 1824 filepos = offset; 1825 return offset; 1826 } 1827 1828 int 1829 dir (char *dirname) 1830 { 1831 #ifndef NO_DECOMPRESSION 1832 compressed_file = 0; 1833 #endif /* NO_DECOMPRESSION */ 1834 1835 if (!(dirname = setup_part (dirname))) 1836 return 0; 1837 1838 if (*dirname != '/') 1839 errnum = ERR_BAD_FILENAME; 1840 1841 if (fsys_type == NUM_FSYS) 1842 errnum = ERR_FSYS_MOUNT; 1843 1844 if (errnum) 1845 return 0; 1846 1847 /* set "dir" function to list completions */ 1848 print_possibilities = 1; 1849 1850 return (*(fsys_table[fsys_type].dir_func)) (dirname); 1851 } 1852 #endif /* STAGE1_5 */ 1853 1854 void 1855 grub_close (void) 1856 { 1857 #ifndef NO_BLOCK_FILES 1858 if (block_file) 1859 return; 1860 #endif /* NO_BLOCK_FILES */ 1861 1862 if (fsys_table[fsys_type].close_func != 0) 1863 (*(fsys_table[fsys_type].close_func)) (); 1864 } 1865