| /* |
| * This file is subject to the terms and conditions of the GNU General Public |
| * License. See the file "COPYING" in the main directory of this archive |
| * for more details. |
| * |
| * Copyright (C) Hewlett-Packard (Paul Bame) paul_bame@hp.com |
| */ |
| #include "common.h" |
| #include <stdio.h> |
| |
| int |
| is_extended(int id) |
| { |
| switch(id) |
| { |
| case DOS_EXTENDED_PARTITION: |
| case LINUX_EXTENDED_PARTITION: |
| case WIN98_EXTENDED_PARTITION: |
| return 1; |
| } |
| return 0; |
| } |
| |
| int |
| load_partitions(int bootdev, struct diskpartition *mptab, int maxparts) |
| { |
| struct firstblock fb; |
| struct partition *ptab = &fb.part[0]; |
| int i; |
| int ex = -1; |
| int extnum = 4; |
| unsigned offset; |
| |
| /* seekread MBR */ |
| if (seekread(bootdev, (char *)&fb, sizeof fb, 0) == -1) |
| return 0; |
| |
| if (fb.dosmagic[0] != 0x55 || fb.dosmagic[1] != 0xaa) |
| return 0; |
| |
| for (i = 0; i < 4; i++) |
| { |
| mptab[i].start = __le32_to_cpu(ptab[i].start_sect); |
| mptab[i].length = __le32_to_cpu(ptab[i].nr_sects); |
| mptab[i].id = ptab[i].sys_ind; |
| if (is_extended(ptab[i].sys_ind)) |
| ex = i; |
| } |
| |
| if (ex != -1) |
| { |
| offset = mptab[ex].start; |
| while (extnum < maxparts) |
| { |
| /* we're currently using 32-bit file seeks which is ok since |
| * the IPL is also limited to 2G right now. On disks > 4GB |
| * this next read may fail. Handle that gracefully. |
| * Yes, we know newer IODC can read/write > 2GB but |
| * it would confuse too many people if the docs attempted |
| * to explain for no tangible benefit. And moving boot disks |
| * between systems will always work (assuming a useable |
| * kernel is present). |
| */ |
| if (offset >= (2 * (GB / 512))) { /* weird () to quiet compiler */ |
| printf("Skipping extended partition %d - beyond reach of IPL\n\r", |
| extnum + 1); |
| break; |
| } |
| if (seekread(bootdev, (char *)&fb, sizeof fb, 512 * offset) == -1) { |
| printf("seekread(bootdev,..., 512 * 0x%x) failed!\n\r", offset); |
| break; |
| } |
| if (fb.dosmagic[0] != 0x55 || fb.dosmagic[1] != 0xaa) |
| { |
| printf("Bad DOS magic in extended partition\n\r"); |
| break; |
| } |
| |
| mptab[extnum].start = __le32_to_cpu(ptab[0].start_sect) + offset; |
| mptab[extnum].length = __le32_to_cpu(ptab[0].nr_sects); |
| mptab[extnum].id = ptab[0].sys_ind; |
| extnum++; |
| if (!is_extended(ptab[1].sys_ind)) |
| break; |
| offset = mptab[ex].start + __le32_to_cpu(ptab[1].start_sect); |
| } |
| } |
| |
| return 1; |
| } |
| |
| void |
| print_ptab(struct diskpartition *mptab, int maxparts) |
| { |
| int i; |
| for (i = 0; i < maxparts; i++) |
| { |
| if (mptab[i].id != 0) |
| printf("/dev/ida%-2d %02x %10u %10u\n\r", |
| i + 1, mptab[i].id, |
| mptab[i].start, |
| mptab[i].length); |
| } |
| } |
| |
| void |
| print_ptab_pretty(struct diskpartition *mptab, int maxparts) |
| { |
| int i; |
| const int mbshift = 20 - 9; |
| |
| printf("Partition Start(MB) End(MB) Id Type\n\r"); |
| for (i = 0; i < maxparts; i++) |
| { |
| if (mptab[i].id != 0 && ! is_extended(mptab[i].id)) |
| printf("%-9x %7d %5d %2x %s\n\r", |
| i + 1, |
| 1 + (mptab[i].start >> mbshift), |
| (mptab[i].start + mptab[i].length) >> mbshift, |
| mptab[i].id, |
| mptab[i].id == LINUX_EXT2_PARTITION ? "ext2" : |
| (mptab[i].id == LINUX_SWAP_PARTITION ? "swap" : |
| (mptab[i].id == LINUX_RAID_PARTITION ? "RAID" : |
| (mptab[i].id == PALO_PARTITION ? "Palo" : "Unknown")))); |
| } |
| } |
| |