📄 disk_io.c
字号:
intdevwrite (unsigned long sector, unsigned long sector_count, char *buf){#if defined(GRUB_UTIL) && defined(__linux__) if (current_partition != 0xFFFFFF && is_disk_device (device_map, current_drive)) { /* If the grub shell is running under Linux and the user wants to embed a Stage 1.5 into a partition instead of a MBR, use system calls directly instead of biosdisk, because of the bug in Linux. *sigh* */ return write_to_partition (device_map, current_drive, current_partition, sector, sector_count, buf); } else#endif /* GRUB_UTIL && __linux__ */ { //unsigned long i; for (i = 0; i < sector_count; i++) { if (! rawwrite (current_drive, part_start + sector + i, buf + (i << SECTOR_BITS))) return 0; } return 1; }}#endif /* ! STAGE1_5 */#ifndef STAGE1_5intset_bootdev (int hdbias){ int j; /* Copy the boot partition information to 0x7be-0x7fd for chain-loading. */ if ((saved_drive & 0x80) && cur_part_addr) { if (rawread (saved_drive, cur_part_offset, 0, SECTOR_SIZE, (char *) SCRATCHADDR)) { char *dst, *src; /* Need only the partition table. XXX: We cannot use grub_memmove because BOOT_PART_TABLE (0x07be) is less than 0x1000. */ dst = (char *) BOOT_PART_TABLE; src = (char *) SCRATCHADDR + BOOTSEC_PART_OFFSET; while (dst < (char *) BOOT_PART_TABLE + BOOTSEC_PART_LENGTH) *dst++ = *src++; /* Clear the active flag of all partitions. */ for (i = 0; i < 4; i++) PC_SLICE_FLAG (BOOT_PART_TABLE - BOOTSEC_PART_OFFSET, i) = 0; /* Set the active flag of the booted partition. */ *((unsigned char *) cur_part_addr) = PC_SLICE_FLAG_BOOTABLE; boot_part_addr = cur_part_addr; } else { return 0; } } /* * Set BSD boot device. */ i = (saved_partition >> 16) + 2; if (saved_partition == 0xFFFFFF) i = 1; else if ((saved_partition >> 16) == 0xFF) i = 0; /* FIXME: extremely evil hack!!! */ j = 2; if (saved_drive & 0x80) j = bsd_evil_hack; return MAKEBOOTDEV (j, (i >> 4), (i & 0xF), ((saved_drive - hdbias) & 0x7F), ((saved_partition >> 8) & 0xFF));}#endif /* STAGE1_5 */#ifndef STAGE1_5/* * This prints the filesystem type or gives relevant information. */voidprint_fsys_type (void){ if (! do_completion) { printf (" Filesystem type "); if (fsys_type != NUM_FSYS) printf ("is %s, ", fsys_table[fsys_type].name); else printf ("unknown, "); if (current_partition == 0xFFFFFF) printf ("using whole disk\n"); else printf ("partition type 0x%02X\n", current_slice & 0xFF); }}#endif /* ! STAGE1_5 */ /* Get next BSD partition in current PC slice. */static intnext_bsd_partition (/*unsigned long drive, unsigned long *partition, int *type, unsigned long *start, unsigned long *len, char *buf*/void){// int i; bsd_part_no = (*next_partition_partition & 0xFF00) >> 8;#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_bsd_partition: 001\n");#endif /* If this is the first time... */ if (bsd_part_no == 0xFF) { /* Check if the BSD label is within current PC slice. */ if (*next_partition_len < BSD_LABEL_SECTOR + 1) { errnum = ERR_BAD_PART_TABLE; return 0; }#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_bsd_partition: 002\n");#endif /* Read the BSD label. */ if (! rawread (next_partition_drive, *next_partition_start + BSD_LABEL_SECTOR, 0, SECTOR_SIZE, next_partition_buf)) return 0;#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_bsd_partition: 003\n");#endif /* Check if it is valid. */ if (! BSD_LABEL_CHECK_MAG (next_partition_buf)) { errnum = ERR_BAD_PART_TABLE; return 0; } bsd_part_no = -1; }#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_bsd_partition: 004\n");#endif /* Search next valid BSD partition. */ if (BSD_LABEL_NPARTS (next_partition_buf) <= BSD_LABEL_NPARTS_MAX) for (i = bsd_part_no + 1; i < BSD_LABEL_NPARTS (next_partition_buf); i++) { if (BSD_PART_TYPE (next_partition_buf, i)) { /* Note that *TYPE and *PARTITION were set for current PC slice. */ *next_partition_type = (BSD_PART_TYPE (next_partition_buf, i) << 8) | (*next_partition_type & 0xFF); *next_partition_start = BSD_PART_START (next_partition_buf, i); *next_partition_len = BSD_PART_LENGTH (next_partition_buf, i); *next_partition_partition = (*next_partition_partition & 0xFF00FF) | (i << 8);#ifndef STAGE1_5 /* XXX */ if ((next_partition_drive & 0x80) && BSD_LABEL_DTYPE (next_partition_buf) == DTYPE_SCSI) bsd_evil_hack = 4;#endif /* ! STAGE1_5 */ return 1; } }#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_bsd_partition: 005\n");#endif errnum = ERR_NO_PART; return 0;} /* Get next PC slice. Be careful of that this function may return an empty PC slice (i.e. a partition whose type is zero) as well. */static intnext_pc_slice (void){redo:#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_pc_slice: 001\n");#endif pc_slice_no = (*next_partition_partition & 0xFF0000) >> 16; /* If this is the first time... */ if (pc_slice_no == 0xFF) { *next_partition_offset = 0; *next_partition_ext_offset = 0; *next_partition_entry = -1; pc_slice_no = -1; }#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_pc_slice: 002\n");#endif /* Read the MBR or the boot sector of the extended partition. */ if (! rawread (next_partition_drive, *next_partition_offset, 0, SECTOR_SIZE, next_partition_buf)) return 0; /* Check if it is valid. */ if (! PC_MBR_CHECK_SIG (next_partition_buf)) { errnum = ERR_BAD_PART_TABLE; return 0; }next_entry:#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_pc_slice: 003\n");#endif /* Increase the entry number. */ (*next_partition_entry)++; /* If this is out of current partition table... */ if (*next_partition_entry == PC_SLICE_MAX) {// int i; /* Search the first extended partition in current table. */ for (i = 0; i < PC_SLICE_MAX; i++) { if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (next_partition_buf, i))) { /* Found. Set the new offset and the entry number, and restart this function. */ *next_partition_offset = *next_partition_ext_offset + PC_SLICE_START (next_partition_buf, i); if (! *next_partition_ext_offset) *next_partition_ext_offset = *next_partition_offset; *next_partition_entry = -1;#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_pc_slice: recursive call\n");#endif#if 0 return next_pc_slice (); /* FIXME: Recursive!!!! */#else goto redo;#endif } }#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_pc_slice: return error\n");#endif errnum = ERR_NO_PART; return 0; } *next_partition_type = PC_SLICE_TYPE (next_partition_buf, *next_partition_entry); *next_partition_start = *next_partition_offset + PC_SLICE_START (next_partition_buf, *next_partition_entry); *next_partition_len = PC_SLICE_LENGTH (next_partition_buf, *next_partition_entry); /* The calculation of a PC slice number is complicated, because of the rather odd definition of extended partitions. Even worse, there is no guarantee that this is consistent with every operating systems. Uggh. */ if (((int)pc_slice_no) >= PC_SLICE_MAX - 1 /* if it is a logical partition */ && (PC_SLICE_ENTRY_IS_EMPTY (next_partition_buf, *next_partition_entry))) /* ignore the garbage entry(typically all bytes are 0xF6). */ goto next_entry;#if 1 /* disable partition id 00. */ if (((int)pc_slice_no) >= PC_SLICE_MAX - 1 /* if it is a logical partition */ && *next_partition_type == PC_SLICE_TYPE_NONE) /* ignore the partition with id=00. */ goto next_entry;#else /* enable partition id 00. */#endif if (((int)pc_slice_no) < PC_SLICE_MAX - 1 || ! IS_PC_SLICE_TYPE_EXTENDED (*next_partition_type)) pc_slice_no++;#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_pc_slice: return success\n");#endif *next_partition_partition = (pc_slice_no << 16) | 0xFFFF; return 1;}/* Get the information on next partition on the drive DRIVE. The caller must not modify the contents of the arguments when iterating this function. The partition representation in GRUB will be stored in *PARTITION. Likewise, the partition type in *TYPE, the start sector in *START, the length in *LEN, the offset of the partition table in *OFFSET, the entry number in the table in *ENTRY, the offset of the extended partition in *EXT_OFFSET. BUF is used to store a MBR, the boot sector of a partition, or a BSD label sector, and it must be at least 512 bytes length. When calling this function first, *PARTITION must be initialized to 0xFFFFFF. The return value is zero if fails, otherwise non-zero. */intnext_partition (/*unsigned long drive, unsigned long dest, unsigned long *partition, int *type, unsigned long *start, unsigned long *len, unsigned long *offset, int *entry, unsigned long *ext_offset, char *buf*/void){ /* Start the body of this function. */#ifndef STAGE1_5 if ((current_drive == NETWORK_DRIVE) || (current_drive == PXE_DRIVE)) return 0;#endif /* If previous partition is a BSD partition or a PC slice which contains BSD partitions... */ if ((*next_partition_partition != 0xFFFFFF && IS_PC_SLICE_TYPE_BSD (*next_partition_type & 0xff)) || ! (next_partition_drive & 0x80)) {#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_partition: bsd check begin\n");#endif if (*next_partition_type == PC_SLICE_TYPE_NONE) *next_partition_type = PC_SLICE_TYPE_FREEBSD; /* Get next BSD partition, if any. */ if (next_bsd_partition (/*next_partition_drive, next_partition_partition, next_partition_type, next_partition_start, next_partition_len, next_partition_buf*/)) return 1; /* If the destination partition is a BSD partition and current BSD partition has any error, abort the operation. */ if ((next_partition_dest & 0xFF00) != 0xFF00 && ((next_partition_dest & 0xFF0000) == 0xFF0000 || (next_partition_dest & 0xFF0000) == (*next_partition_partition & 0xFF0000))) return 0; /* Ignore the error. */ errnum = ERR_NONE; }#ifndef STAGE1_5//if (debug == -2) grub_printf ("next_partition: next_pc_slice begin\n");#endif return next_pc_slice ();}static voidattempt_mount (void){#ifndef STAGE1_5 for (fsys_type = 0; fsys_type < NUM_FSYS; fsys_type++) {// if (fsys_type >= 4) continue; if (errnum = 0, ((fsys_table[fsys_type].mount_func) ())) break; } if (fsys_type == NUM_FSYS && errnum == ERR_NONE) errnum = ERR_FSYS_MOUNT;#else fsys_type = 0; if ((*(fsys_table[fsys_type].mount_func)) () != 1) { fsys_type = NUM_FSYS; errnum = ERR_FSYS_MOUNT; }#endif}/* * This performs a "mount" on the current device, both drive and partition * number. */intopen_device (void){ if (open_partition ()) attempt_mount (); if (errnum != ERR_NONE) return 0; return 1;} /* For simplicity. */static unsigned long next_part (void);static unsigned longnext_part (void){ next_partition_drive = current_drive; next_partition_dest = dest_partition; next_partition_partition = ¤t_partition; next_partition_type = ¤t_slice; next_partition_start = &part_start; next_partition_len = &part_length; next_partition_offset = &part_offset; next_partition_entry = &entry; next_partition_ext_offset = &ext_offset; next_partition_buf = mbr; i = next_partition (); bsd_part_no = (current_partition >> 8) & 0xFF; pc_slice_no = current_partition >> 16; return i;}#ifndef STAGE1_5static voidcheck_and_print_mount (void){ attempt_mount (); if (errnum == ERR_FSYS_MOUNT) errnum = ERR_NONE; if (!errnum) print_fsys_type (); print_error ();}#endif /* ! STAGE1_5 *//* Open a partition. */intreal_open_partition (int flags){#if defined(STAGE1_5) || defined(GRUB_UTIL)// char mbr[SECTOR_SIZE];#endif// int bsd_part, pc_slice; dest_partition = current_partition;#ifndef STAGE1_5 /* network drive */ if ((current_drive == NETWORK_DRIVE) || (current_drive==PXE_DRIVE)) return 1; if (! sane_partition ()) return 0;#endif bsd_evil_hack = 0; current_slice = 0; part_start = 0; /* Make sure that buf_geom is valid. */ if (buf_drive != current_drive) { if (get_diskinfo (current_drive, &buf_geom)) { errnum = ERR_NO_DISK; return 0; } buf_drive = current_drive; buf_track = -1; } part_length = buf_geom.total_sectors; /* If this is the whole disk, return here. */ if (! flags && current_partition == 0xFFFFFF) return 1; if (flags) dest_partition = 0xFFFFFF; /* Initialize CURRENT_PARTITION for next_partition. */ current_partition = 0xFFFFFF; while (next_part ()) {#ifndef STAGE1_5 loop_start: cur_part_offset = part_offset; cur_part_addr = BOOT_PART_TABLE + (entry << 4);//if (debug == -2) grub_printf ("real_open_partition: outer loop: 001\n");#endif /* ! STAGE1_5 */ /* If this is a valid partition... */ if (current_slice) {#ifndef STAGE1_5 /* Display partition information. */ if (flags && ! IS_PC_SLICE_TYPE_EXTENDED (current_slice)) { if (! do_completion) { if (current_drive & 0x80) { int active = (PC_SLICE_FLAG (mbr, entry) == PC_SLICE_FLAG_BOOTABLE); grub_printf (" Partition num: %d%s, ", (current_partition >> 16), (active ? ", active": "")); }//if (debug == -2) grub_printf ("real_open_partition: outer loop: 002\n"); if (! IS_PC_SLICE_TYPE_BSD (current_slice)) check_and_print_mount (); else { int got_part = 0; int saved_slice = current_slice;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -