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 int 1017 set_bootfs(char *fsname) 1018 { 1019 grub_memmove(current_bootfs, fsname, MAXNAMELEN); 1020 } 1021 1022 char * 1023 set_device (char *device) 1024 { 1025 #ifdef STAGE1_5 1026 /* In Stage 1.5, the first 4 bytes of FILENAME has a device number. */ 1027 unsigned long dev = *((unsigned long *) device); 1028 int drive = (dev >> 24) & 0xFF; 1029 int partition = dev & 0xFFFFFF; 1030 1031 /* If DRIVE is disabled, use SAVED_DRIVE instead. */ 1032 if (drive == GRUB_INVALID_DRIVE) 1033 current_drive = saved_drive; 1034 else 1035 current_drive = drive; 1036 1037 /* The `partition' part must always have a valid number. */ 1038 current_partition = partition; 1039 1040 return device + sizeof (unsigned long); 1041 1042 #else /* ! STAGE1_5 */ 1043 1044 int result = 0; 1045 1046 incomplete = 0; 1047 disk_choice = 1; 1048 part_choice = PART_UNSPECIFIED; 1049 current_drive = saved_drive; 1050 current_partition = 0xFFFFFF; 1051 1052 if (*device == '(' && !*(device + 1)) 1053 /* user has given '(' only, let disk_choice handle what disks we have */ 1054 return device + 1; 1055 1056 if (*device == '(' && *(++device)) 1057 { 1058 if (*device != ',' && *device != ')') 1059 { 1060 char ch = *device; 1061 #ifdef SUPPORT_NETBOOT 1062 if (*device == 'f' || *device == 'h' 1063 || (*device == 'n' && network_ready) 1064 || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE)) 1065 #else 1066 if (*device == 'f' || *device == 'h' 1067 || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE)) 1068 #endif /* SUPPORT_NETBOOT */ 1069 { 1070 /* user has given '([fhn]', check for resp. add 'd' and 1071 let disk_choice handle what disks we have */ 1072 if (!*(device + 1)) 1073 { 1074 device++; 1075 *device++ = 'd'; 1076 *device = '\0'; 1077 return device; 1078 } 1079 else if (*(device + 1) == 'd' && !*(device + 2)) 1080 return device + 2; 1081 } 1082 1083 if ((*device == 'f' 1084 || *device == 'h' 1085 #ifdef SUPPORT_NETBOOT 1086 || (*device == 'n' && network_ready) 1087 #endif 1088 || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE)) 1089 && (device += 2, (*(device - 1) != 'd'))) 1090 errnum = ERR_NUMBER_PARSING; 1091 1092 #ifdef SUPPORT_NETBOOT 1093 if (ch == 'n' && network_ready) 1094 current_drive = NETWORK_DRIVE; 1095 else 1096 #endif /* SUPPORT_NETBOOT */ 1097 { 1098 if (ch == 'c' && cdrom_drive != GRUB_INVALID_DRIVE) 1099 current_drive = cdrom_drive; 1100 else 1101 { 1102 safe_parse_maxint (&device, (int *) ¤t_drive); 1103 1104 disk_choice = 0; 1105 if (ch == 'h') 1106 current_drive += 0x80; 1107 } 1108 } 1109 } 1110 1111 if (errnum) 1112 return 0; 1113 1114 if (*device == ')') 1115 { 1116 part_choice = PART_CHOSEN; 1117 result = 1; 1118 } 1119 else if (*device == ',') 1120 { 1121 /* Either an absolute PC, BSD, or Solaris partition. */ 1122 disk_choice = 0; 1123 part_choice ++; 1124 device++; 1125 1126 if (*device >= '0' && *device <= '9') 1127 { 1128 part_choice ++; 1129 current_partition = 0; 1130 1131 if (!(current_drive & 0x80) 1132 || !safe_parse_maxint (&device, (int *) ¤t_partition) 1133 || current_partition > 254) 1134 { 1135 errnum = ERR_DEV_FORMAT; 1136 return 0; 1137 } 1138 1139 current_partition = (current_partition << 16) + 0xFFFF; 1140 1141 if (*device == ',') 1142 device++; 1143 1144 if (*device >= 'a' && *device <= 'p') 1145 { 1146 current_partition = (((*(device++) - 'a') << 8) 1147 | (current_partition & 0xFF00FF)); 1148 } 1149 } 1150 else if (*device >= 'a' && *device <= 'p') 1151 { 1152 part_choice ++; 1153 current_partition = ((*(device++) - 'a') << 8) | 0xFF00FF; 1154 } 1155 1156 if (*device == ')') 1157 { 1158 if (part_choice == PART_DISK) 1159 { 1160 current_partition = saved_partition; 1161 part_choice ++; 1162 } 1163 1164 result = 1; 1165 } 1166 } 1167 } 1168 1169 if (! sane_partition ()) 1170 return 0; 1171 1172 if (result) 1173 return device + 1; 1174 else 1175 { 1176 if (!*device) 1177 incomplete = 1; 1178 errnum = ERR_DEV_FORMAT; 1179 } 1180 1181 return 0; 1182 1183 #endif /* ! STAGE1_5 */ 1184 } 1185 1186 /* 1187 * This performs a "mount" on the current device, both drive and partition 1188 * number. 1189 */ 1190 1191 int 1192 open_device (void) 1193 { 1194 if (open_partition ()) 1195 attempt_mount (); 1196 1197 if (errnum != ERR_NONE) 1198 return 0; 1199 1200 return 1; 1201 } 1202 1203 1204 #ifndef STAGE1_5 1205 int 1206 set_bootdev (int hdbias) 1207 { 1208 int i, j; 1209 1210 /* Copy the boot partition information to 0x7be-0x7fd for chain-loading. */ 1211 if ((saved_drive & 0x80) && cur_part_addr) 1212 { 1213 if (rawread (saved_drive, cur_part_offset, 1214 0, SECTOR_SIZE, (char *) SCRATCHADDR)) 1215 { 1216 char *dst, *src; 1217 1218 /* Need only the partition table. 1219 XXX: We cannot use grub_memmove because BOOT_PART_TABLE 1220 (0x07be) is less than 0x1000. */ 1221 dst = (char *) BOOT_PART_TABLE; 1222 src = (char *) SCRATCHADDR + BOOTSEC_PART_OFFSET; 1223 while (dst < (char *) BOOT_PART_TABLE + BOOTSEC_PART_LENGTH) 1224 *dst++ = *src++; 1225 1226 /* Set the active flag of the booted partition. */ 1227 for (i = 0; i < 4; i++) 1228 PC_SLICE_FLAG (BOOT_PART_TABLE, i) = 0; 1229 1230 *((unsigned char *) cur_part_addr) = PC_SLICE_FLAG_BOOTABLE; 1231 boot_part_addr = cur_part_addr; 1232 } 1233 else 1234 return 0; 1235 } 1236 1237 /* 1238 * Set BSD boot device. 1239 */ 1240 i = (saved_partition >> 16) + 2; 1241 if (saved_partition == 0xFFFFFF) 1242 i = 1; 1243 else if ((saved_partition >> 16) == 0xFF) 1244 i = 0; 1245 1246 /* FIXME: extremely evil hack!!! */ 1247 j = 2; 1248 if (saved_drive & 0x80) 1249 j = bsd_evil_hack; 1250 1251 return MAKEBOOTDEV (j, (i >> 4), (i & 0xF), 1252 ((saved_drive - hdbias) & 0x7F), 1253 ((saved_partition >> 8) & 0xFF)); 1254 } 1255 #endif /* STAGE1_5 */ 1256 1257 1258 static char * 1259 setup_part (char *filename) 1260 { 1261 #ifdef STAGE1_5 1262 1263 if (! (filename = set_device (filename))) 1264 { 1265 current_drive = GRUB_INVALID_DRIVE; 1266 return 0; 1267 } 1268 1269 # ifndef NO_BLOCK_FILES 1270 if (*filename != '/') 1271 open_partition (); 1272 else 1273 # endif /* ! NO_BLOCK_FILES */ 1274 open_device (); 1275 1276 #else /* ! STAGE1_5 */ 1277 1278 if (*filename == '(') 1279 { 1280 if ((filename = set_device (filename)) == 0) 1281 { 1282 current_drive = GRUB_INVALID_DRIVE; 1283 return 0; 1284 } 1285 # ifndef NO_BLOCK_FILES 1286 if (*filename != '/' && current_drive != NETWORK_DRIVE) 1287 open_partition (); 1288 else 1289 # endif /* ! NO_BLOCK_FILES */ 1290 open_device (); 1291 } 1292 else if (saved_drive != current_drive 1293 || saved_partition != current_partition 1294 || (*filename == '/' && fsys_type == NUM_FSYS) 1295 || buf_drive == -1) 1296 { 1297 current_drive = saved_drive; 1298 current_partition = saved_partition; 1299 /* allow for the error case of "no filesystem" after the partition 1300 is found. This makes block files work fine on no filesystem */ 1301 # ifndef NO_BLOCK_FILES 1302 if (*filename != '/' && current_drive != NETWORK_DRIVE) 1303 open_partition (); 1304 else 1305 # endif /* ! NO_BLOCK_FILES */ 1306 open_device (); 1307 } 1308 1309 #endif /* ! STAGE1_5 */ 1310 1311 if (errnum && (*filename == '/' || errnum != ERR_FSYS_MOUNT)) 1312 return 0; 1313 else 1314 errnum = 0; 1315 1316 #ifndef STAGE1_5 1317 if (!sane_partition ()) 1318 return 0; 1319 #endif 1320 1321 return filename; 1322 } 1323 1324 1325 #ifndef STAGE1_5 1326 /* 1327 * This prints the filesystem type or gives relevant information. 1328 */ 1329 1330 void 1331 print_fsys_type (void) 1332 { 1333 if (! do_completion) 1334 { 1335 grub_printf (" Filesystem type "); 1336 1337 if (fsys_type != NUM_FSYS) 1338 grub_printf ("is %s, ", fsys_table[fsys_type].name); 1339 else 1340 grub_printf ("unknown, "); 1341 1342 if (current_partition == 0xFFFFFF) 1343 grub_printf ("using whole disk\n"); 1344 else 1345 grub_printf ("partition type 0x%x\n", current_slice & 0xFF); 1346 } 1347 } 1348 #endif /* STAGE1_5 */ 1349 1350 #ifndef STAGE1_5 1351 /* If DO_COMPLETION is true, just print NAME. Otherwise save the unique 1352 part into UNIQUE_STRING. */ 1353 void 1354 print_a_completion (char *name) 1355 { 1356 /* If NAME is "." or "..", do not count it. */ 1357 if (grub_strcmp (name, ".") == 0 || grub_strcmp (name, "..") == 0) 1358 return; 1359 1360 if (do_completion) 1361 { 1362 char *buf = unique_string; 1363 1364 if (! unique) 1365 while ((*buf++ = *name++)) 1366 ; 1367 else 1368 { 1369 while (*buf && (*buf == *name)) 1370 { 1371 buf++; 1372 name++; 1373 } 1374 /* mismatch, strip it. */ 1375 *buf = '\0'; 1376 } 1377 } 1378 else 1379 grub_printf (" %s", name); 1380 1381 unique++; 1382 } 1383 1384 /* 1385 * This lists the possible completions of a device string, filename, or 1386 * any sane combination of the two. 1387 */ 1388 1389 int 1390 print_completions (int is_filename, int is_completion) 1391 { 1392 char *buf = (char *) COMPLETION_BUF; 1393 char *ptr = buf; 1394 1395 unique_string = (char *) UNIQUE_BUF; 1396 *unique_string = 0; 1397 unique = 0; 1398 do_completion = is_completion; 1399 1400 if (! is_filename) 1401 { 1402 /* Print the completions of builtin commands. */ 1403 struct builtin **builtin; 1404 1405 if (! is_completion) 1406 grub_printf (" Possible commands are:"); 1407 1408 for (builtin = builtin_table; (*builtin); builtin++) 1409 { 1410 /* If *BUILTIN cannot be run in the command-line, skip it. */ 1411 if (! ((*builtin)->flags & BUILTIN_CMDLINE)) 1412 continue; 1413 1414 if (substring (buf, (*builtin)->name) <= 0) 1415 print_a_completion ((*builtin)->name); 1416 } 1417 1418 if (is_completion && *unique_string) 1419 { 1420 if (unique == 1) 1421 { 1422 char *u = unique_string + grub_strlen (unique_string); 1423 1424 *u++ = ' '; 1425 *u = 0; 1426 } 1427 1428 grub_strcpy (buf, unique_string); 1429 } 1430 1431 if (! is_completion) 1432 grub_putchar ('\n'); 1433 1434 print_error (); 1435 do_completion = 0; 1436 if (errnum) 1437 return -1; 1438 else 1439 return unique - 1; 1440 } 1441 1442 if (*buf == '/' || (ptr = set_device (buf)) || incomplete) 1443 { 1444 errnum = 0; 1445 1446 if (*buf == '(' && (incomplete || ! *ptr)) 1447 { 1448 if (! part_choice) 1449 { 1450 /* disk completions */ 1451 int disk_no, i, j; 1452 struct geometry geom; 1453 1454 if (! is_completion) 1455 grub_printf (" Possible disks are: "); 1456 1457 if (!ptr 1458 || *(ptr-1) != 'd' 1459 #ifdef SUPPORT_NETBOOT 1460 || *(ptr-2) != 'n' 1461 #endif /* SUPPORT_NETBOOT */ 1462 || *(ptr-2) != 'c') 1463 { 1464 for (i = (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'h') ? 1:0); 1465 i < (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'f') ? 1:2); 1466 i++) 1467 { 1468 for (j = 0; j < 8; j++) 1469 { 1470 disk_no = (i * 0x80) + j; 1471 if ((disk_choice || disk_no == current_drive) 1472 && ! get_diskinfo (disk_no, &geom)) 1473 { 1474 char dev_name[8]; 1475 1476 grub_sprintf (dev_name, "%cd%d", i ? 'h':'f', j); 1477 print_a_completion (dev_name); 1478 } 1479 } 1480 } 1481 } 1482 1483 if (cdrom_drive != GRUB_INVALID_DRIVE 1484 && (disk_choice || cdrom_drive == current_drive) 1485 && (!ptr 1486 || *(ptr-1) == '(' 1487 || (*(ptr-1) == 'd' && *(ptr-2) == 'c'))) 1488 print_a_completion ("cd"); 1489 1490 # ifdef SUPPORT_NETBOOT 1491 if (network_ready 1492 && (disk_choice || NETWORK_DRIVE == current_drive) 1493 && (!ptr 1494 || *(ptr-1) == '(' 1495 || (*(ptr-1) == 'd' && *(ptr-2) == 'n'))) 1496 print_a_completion ("nd"); 1497 # endif /* SUPPORT_NETBOOT */ 1498 1499 if (is_completion && *unique_string) 1500 { 1501 ptr = buf; 1502 while (*ptr != '(') 1503 ptr--; 1504 ptr++; 1505 grub_strcpy (ptr, unique_string); 1506 if (unique == 1) 1507 { 1508 ptr += grub_strlen (ptr); 1509 if (*unique_string == 'h') 1510 { 1511 *ptr++ = ','; 1512 *ptr = 0; 1513 } 1514 else 1515 { 1516 *ptr++ = ')'; 1517 *ptr = 0; 1518 } 1519 } 1520 } 1521 1522 if (! is_completion) 1523 grub_putchar ('\n'); 1524 } 1525 else 1526 { 1527 /* partition completions */ 1528 if (part_choice == PART_CHOSEN 1529 && open_partition () 1530 && ! IS_PC_SLICE_TYPE_BSD (current_slice)) 1531 { 1532 unique = 1; 1533 ptr = buf + grub_strlen (buf); 1534 if (*(ptr - 1) != ')') 1535 { 1536 *ptr++ = ')'; 1537 *ptr = 0; 1538 } 1539 } 1540 else 1541 { 1542 if (! is_completion) 1543 grub_printf (" Possible partitions are:\n"); 1544 real_open_partition (1); 1545 1546 if (is_completion && *unique_string) 1547 { 1548 ptr = buf; 1549 while (*ptr++ != ',') 1550 ; 1551 grub_strcpy (ptr, unique_string); 1552 } 1553 } 1554 } 1555 } 1556 else if (ptr && *ptr == '/') 1557 { 1558 /* filename completions */ 1559 if (! is_completion) 1560 grub_printf (" Possible files are:"); 1561 1562 dir (buf); 1563 1564 if (is_completion && *unique_string) 1565 { 1566 ptr += grub_strlen (ptr); 1567 while (*ptr != '/') 1568 ptr--; 1569 ptr++; 1570 1571 grub_strcpy (ptr, unique_string); 1572 1573 if (unique == 1) 1574 { 1575 ptr += grub_strlen (unique_string); 1576 1577 /* Check if the file UNIQUE_STRING is a directory. */ 1578 *ptr = '/'; 1579 *(ptr + 1) = 0; 1580 1581 dir (buf); 1582 1583 /* Restore the original unique value. */ 1584 unique = 1; 1585 1586 if (errnum) 1587 { 1588 /* Regular file */ 1589 errnum = 0; 1590 *ptr = ' '; 1591 *(ptr + 1) = 0; 1592 } 1593 } 1594 } 1595 1596 if (! is_completion) 1597 grub_putchar ('\n'); 1598 } 1599 else 1600 errnum = ERR_BAD_FILENAME; 1601 } 1602 1603 print_error (); 1604 do_completion = 0; 1605 if (errnum) 1606 return -1; 1607 else 1608 return unique - 1; 1609 } 1610 #endif /* STAGE1_5 */ 1611 1612 1613 /* 1614 * This is the generic file open function. 1615 */ 1616 1617 int 1618 grub_open (char *filename) 1619 { 1620 #ifndef NO_DECOMPRESSION 1621 compressed_file = 0; 1622 #endif /* NO_DECOMPRESSION */ 1623 1624 /* if any "dir" function uses/sets filepos, it must 1625 set it to zero before returning if opening a file! */ 1626 filepos = 0; 1627 1628 if (!(filename = setup_part (filename))) 1629 return 0; 1630 1631 #ifndef NO_BLOCK_FILES 1632 block_file = 0; 1633 #endif /* NO_BLOCK_FILES */ 1634 1635 /* This accounts for partial filesystem implementations. */ 1636 fsmax = MAXINT; 1637 1638 if (*filename != '/' && current_drive != NETWORK_DRIVE) 1639 { 1640 #ifndef NO_BLOCK_FILES 1641 char *ptr = filename; 1642 int tmp, list_addr = BLK_BLKLIST_START; 1643 filemax = 0; 1644 1645 while (list_addr < BLK_MAX_ADDR) 1646 { 1647 tmp = 0; 1648 safe_parse_maxint (&ptr, &tmp); 1649 errnum = 0; 1650 1651 if (*ptr != '+') 1652 { 1653 if ((*ptr && *ptr != '/' && !isspace (*ptr)) 1654 || tmp == 0 || tmp > filemax) 1655 errnum = ERR_BAD_FILENAME; 1656 else 1657 filemax = tmp; 1658 1659 break; 1660 } 1661 1662 /* since we use the same filesystem buffer, mark it to 1663 be remounted */ 1664 fsys_type = NUM_FSYS; 1665 1666 BLK_BLKSTART (list_addr) = tmp; 1667 ptr++; 1668 1669 if (!safe_parse_maxint (&ptr, &tmp) 1670 || tmp == 0 1671 || (*ptr && *ptr != ',' && *ptr != '/' && !isspace (*ptr))) 1672 { 1673 errnum = ERR_BAD_FILENAME; 1674 break; 1675 } 1676 1677 BLK_BLKLENGTH (list_addr) = tmp; 1678 1679 filemax += (tmp * SECTOR_SIZE); 1680 list_addr += BLK_BLKLIST_INC_VAL; 1681 1682 if (*ptr != ',') 1683 break; 1684 1685 ptr++; 1686 } 1687 1688 if (list_addr < BLK_MAX_ADDR && ptr != filename && !errnum) 1689 { 1690 block_file = 1; 1691 BLK_CUR_FILEPOS = 0; 1692 BLK_CUR_BLKLIST = BLK_BLKLIST_START; 1693 BLK_CUR_BLKNUM = 0; 1694 1695 #ifndef NO_DECOMPRESSION 1696 return gunzip_test_header (); 1697 #else /* NO_DECOMPRESSION */ 1698 return 1; 1699 #endif /* NO_DECOMPRESSION */ 1700 } 1701 #else /* NO_BLOCK_FILES */ 1702 errnum = ERR_BAD_FILENAME; 1703 #endif /* NO_BLOCK_FILES */ 1704 } 1705 1706 if (!errnum && fsys_type == NUM_FSYS) 1707 errnum = ERR_FSYS_MOUNT; 1708 1709 # ifndef STAGE1_5 1710 /* set "dir" function to open a file */ 1711 print_possibilities = 0; 1712 # endif 1713 1714 if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename)) 1715 { 1716 #ifndef NO_DECOMPRESSION 1717 return gunzip_test_header (); 1718 #else /* NO_DECOMPRESSION */ 1719 return 1; 1720 #endif /* NO_DECOMPRESSION */ 1721 } 1722 1723 return 0; 1724 } 1725 1726 1727 int 1728 grub_read (char *buf, int len) 1729 { 1730 /* Make sure "filepos" is a sane value */ 1731 if ((filepos < 0) || (filepos > filemax)) 1732 filepos = filemax; 1733 1734 /* Make sure "len" is a sane value */ 1735 if ((len < 0) || (len > (filemax - filepos))) 1736 len = filemax - filepos; 1737 1738 /* if target file position is past the end of 1739 the supported/configured filesize, then 1740 there is an error */ 1741 if (filepos + len > fsmax) 1742 { 1743 errnum = ERR_FILELENGTH; 1744 return 0; 1745 } 1746 1747 #ifndef NO_DECOMPRESSION 1748 if (compressed_file) 1749 return gunzip_read (buf, len); 1750 #endif /* NO_DECOMPRESSION */ 1751 1752 #ifndef NO_BLOCK_FILES 1753 if (block_file) 1754 { 1755 int size, off, ret = 0; 1756 1757 while (len && !errnum) 1758 { 1759 /* we may need to look for the right block in the list(s) */ 1760 if (filepos < BLK_CUR_FILEPOS) 1761 { 1762 BLK_CUR_FILEPOS = 0; 1763 BLK_CUR_BLKLIST = BLK_BLKLIST_START; 1764 BLK_CUR_BLKNUM = 0; 1765 } 1766 1767 /* run BLK_CUR_FILEPOS up to filepos */ 1768 while (filepos > BLK_CUR_FILEPOS) 1769 { 1770 if ((filepos - (BLK_CUR_FILEPOS & ~(SECTOR_SIZE - 1))) 1771 >= SECTOR_SIZE) 1772 { 1773 BLK_CUR_FILEPOS += SECTOR_SIZE; 1774 BLK_CUR_BLKNUM++; 1775 1776 if (BLK_CUR_BLKNUM >= BLK_BLKLENGTH (BLK_CUR_BLKLIST)) 1777 { 1778 BLK_CUR_BLKLIST += BLK_BLKLIST_INC_VAL; 1779 BLK_CUR_BLKNUM = 0; 1780 } 1781 } 1782 else 1783 BLK_CUR_FILEPOS = filepos; 1784 } 1785 1786 off = filepos & (SECTOR_SIZE - 1); 1787 size = ((BLK_BLKLENGTH (BLK_CUR_BLKLIST) - BLK_CUR_BLKNUM) 1788 * SECTOR_SIZE) - off; 1789 if (size > len) 1790 size = len; 1791 1792 disk_read_func = disk_read_hook; 1793 1794 /* read current block and put it in the right place in memory */ 1795 devread (BLK_BLKSTART (BLK_CUR_BLKLIST) + BLK_CUR_BLKNUM, 1796 off, size, buf); 1797 1798 disk_read_func = NULL; 1799 1800 len -= size; 1801 filepos += size; 1802 ret += size; 1803 buf += size; 1804 } 1805 1806 if (errnum) 1807 ret = 0; 1808 1809 return ret; 1810 } 1811 #endif /* NO_BLOCK_FILES */ 1812 1813 if (fsys_type == NUM_FSYS) 1814 { 1815 errnum = ERR_FSYS_MOUNT; 1816 return 0; 1817 } 1818 1819 return (*(fsys_table[fsys_type].read_func)) (buf, len); 1820 } 1821 1822 #ifndef STAGE1_5 1823 /* Reposition a file offset. */ 1824 int 1825 grub_seek (int offset) 1826 { 1827 if (offset > filemax || offset < 0) 1828 return -1; 1829 1830 filepos = offset; 1831 return offset; 1832 } 1833 1834 int 1835 dir (char *dirname) 1836 { 1837 #ifndef NO_DECOMPRESSION 1838 compressed_file = 0; 1839 #endif /* NO_DECOMPRESSION */ 1840 1841 if (!(dirname = setup_part (dirname))) 1842 return 0; 1843 1844 if (*dirname != '/') 1845 errnum = ERR_BAD_FILENAME; 1846 1847 if (fsys_type == NUM_FSYS) 1848 errnum = ERR_FSYS_MOUNT; 1849 1850 if (errnum) 1851 return 0; 1852 1853 /* set "dir" function to list completions */ 1854 print_possibilities = 1; 1855 1856 return (*(fsys_table[fsys_type].dir_func)) (dirname); 1857 } 1858 #endif /* STAGE1_5 */ 1859 1860 void 1861 grub_close (void) 1862 { 1863 #ifndef NO_BLOCK_FILES 1864 if (block_file) 1865 return; 1866 #endif /* NO_BLOCK_FILES */ 1867 1868 if (fsys_table[fsys_type].close_func != 0) 1869 (*(fsys_table[fsys_type].close_func)) (); 1870 } 1871