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