From 041d1ea37802bf7178a31a53f96c26efa6b8fb7b Mon Sep 17 00:00:00 2001 From: James Date: Fri, 16 Nov 2012 10:41:01 +0000 Subject: fish --- grub-core/partmap/acorn.c | 147 ++++++++++++++++++++++ grub-core/partmap/amiga.c | 160 ++++++++++++++++++++++++ grub-core/partmap/apple.c | 199 ++++++++++++++++++++++++++++++ grub-core/partmap/bsdlabel.c | 254 ++++++++++++++++++++++++++++++++++++++ grub-core/partmap/gpt.c | 208 +++++++++++++++++++++++++++++++ grub-core/partmap/msdos.c | 284 +++++++++++++++++++++++++++++++++++++++++++ grub-core/partmap/sun.c | 151 +++++++++++++++++++++++ grub-core/partmap/sunpc.c | 146 ++++++++++++++++++++++ 8 files changed, 1549 insertions(+) create mode 100644 grub-core/partmap/acorn.c create mode 100644 grub-core/partmap/amiga.c create mode 100644 grub-core/partmap/apple.c create mode 100644 grub-core/partmap/bsdlabel.c create mode 100644 grub-core/partmap/gpt.c create mode 100644 grub-core/partmap/msdos.c create mode 100644 grub-core/partmap/sun.c create mode 100644 grub-core/partmap/sunpc.c (limited to 'grub-core/partmap') diff --git a/grub-core/partmap/acorn.c b/grub-core/partmap/acorn.c new file mode 100644 index 0000000..9a68ddd --- /dev/null +++ b/grub-core/partmap/acorn.c @@ -0,0 +1,147 @@ +/* acorn.c - Read Linux/ADFS partition tables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2007 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define LINUX_NATIVE_MAGIC grub_cpu_to_le32 (0xdeafa1de) +#define LINUX_SWAP_MAGIC grub_cpu_to_le32 (0xdeafab1e) +#define LINUX_MAP_ENTRIES (512 / 12) + +#define NONADFS_PARTITION_TYPE_LINUX 9 +#define NONADFS_PARTITION_TYPE_MASK 15 + +struct grub_acorn_boot_block +{ + grub_uint8_t misc[0x1C0]; + struct grub_filecore_disc_record disc_record; + grub_uint8_t flags; + grub_uint16_t start_cylinder; + grub_uint8_t checksum; +} __attribute__ ((packed, aligned)); + +struct linux_part +{ + grub_uint32_t magic; + grub_uint32_t start; + grub_uint32_t size; +}; + +static struct grub_partition_map grub_acorn_partition_map; + +static grub_err_t +acorn_partition_map_find (grub_disk_t disk, struct linux_part *m, + grub_disk_addr_t *sector) +{ + struct grub_acorn_boot_block boot; + grub_err_t err; + unsigned int checksum = 0; + unsigned int heads; + unsigned int sectors_per_cylinder; + int i; + + err = grub_disk_read (disk, 0xC00 / GRUB_DISK_SECTOR_SIZE, 0, + sizeof (struct grub_acorn_boot_block), + &boot); + if (err) + return err; + + if ((boot.flags & NONADFS_PARTITION_TYPE_MASK) != NONADFS_PARTITION_TYPE_LINUX) + goto fail; + + for (i = 0; i != 0x1ff; ++i) + checksum = (checksum & 0xff) + (checksum >> 8) + boot.misc[i]; + + if ((grub_uint8_t) checksum != boot.checksum) + goto fail; + + heads = (boot.disc_record.heads + + ((boot.disc_record.lowsector >> 6) & 1)); + sectors_per_cylinder = boot.disc_record.secspertrack * heads; + *sector = grub_le_to_cpu16 (boot.start_cylinder) * sectors_per_cylinder; + + return grub_disk_read (disk, *sector, 0, + sizeof (struct linux_part) * LINUX_MAP_ENTRIES, + m); + +fail: + return grub_error (GRUB_ERR_BAD_PART_TABLE, + "Linux/ADFS partition map not found"); + +} + + +static grub_err_t +acorn_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + struct grub_partition part; + struct linux_part map[LINUX_MAP_ENTRIES]; + int i; + grub_disk_addr_t sector = 0; + grub_err_t err; + + err = acorn_partition_map_find (disk, map, §or); + if (err) + return err; + + part.partmap = &grub_acorn_partition_map; + + for (i = 0; i != LINUX_MAP_ENTRIES; ++i) + { + if (map[i].magic != LINUX_NATIVE_MAGIC + && map[i].magic != LINUX_SWAP_MAGIC) + return GRUB_ERR_NONE; + + part.start = sector + map[i].start; + part.len = map[i].size; + part.offset = 6; + part.number = part.index = i; + + if (hook (disk, &part)) + return grub_errno; + } + + return GRUB_ERR_NONE; +} + + + +/* Partition map type. */ +static struct grub_partition_map grub_acorn_partition_map = +{ + .name = "acorn", + .iterate = acorn_partition_map_iterate, +}; + +GRUB_MOD_INIT(part_acorn) +{ + grub_partition_map_register (&grub_acorn_partition_map); +} + +GRUB_MOD_FINI(part_acorn) +{ + grub_partition_map_unregister (&grub_acorn_partition_map); +} diff --git a/grub-core/partmap/amiga.c b/grub-core/partmap/amiga.c new file mode 100644 index 0000000..36e318b --- /dev/null +++ b/grub-core/partmap/amiga.c @@ -0,0 +1,160 @@ +/* amiga.c - Read amiga partition tables (RDB). */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2004,2005,2006,2007 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_amiga_rdsk +{ + /* "RDSK". */ + grub_uint8_t magic[4]; +#define GRUB_AMIGA_RDSK_MAGIC "RDSK" + grub_uint32_t size; + grub_int32_t checksum; + grub_uint32_t scsihost; + grub_uint32_t blksz; + grub_uint32_t flags; + grub_uint32_t badblcklst; + grub_uint32_t partitionlst; + grub_uint32_t fslst; + + /* The other information is not important for us. */ +} __attribute__ ((packed)); + +struct grub_amiga_partition +{ + /* "PART". */ + grub_uint8_t magic[4]; +#define GRUB_AMIGA_PART_MAGIC "PART" + grub_int32_t size; + grub_int32_t checksum; + grub_uint32_t scsihost; + grub_uint32_t next; + grub_uint32_t flags; + grub_uint32_t unused1[2]; + grub_uint32_t devflags; + grub_uint8_t namelen; + grub_uint8_t name[31]; + grub_uint32_t unused2[15]; + + grub_uint32_t unused3[3]; + grub_uint32_t heads; + grub_uint32_t unused4; + grub_uint32_t block_per_track; + grub_uint32_t unused5[3]; + grub_uint32_t lowcyl; + grub_uint32_t highcyl; + + grub_uint32_t firstcyl; +} __attribute__ ((packed)); + +static struct grub_partition_map grub_amiga_partition_map; + + + +static grub_err_t +amiga_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + struct grub_partition part; + struct grub_amiga_rdsk rdsk; + int partno = 0; + int next = -1; + unsigned pos; + + /* The RDSK block is one of the first 15 blocks. */ + for (pos = 0; pos < 15; pos++) + { + /* Read the RDSK block which is a descriptor for the entire disk. */ + if (grub_disk_read (disk, pos, 0, sizeof (rdsk), &rdsk)) + return grub_errno; + + if (grub_memcmp (rdsk.magic, GRUB_AMIGA_RDSK_MAGIC, + sizeof (rdsk.magic)) == 0) + { + /* Found the first PART block. */ + next = grub_be_to_cpu32 (rdsk.partitionlst); + break; + } + } + + if (next == -1) + return grub_error (GRUB_ERR_BAD_PART_TABLE, + "Amiga partition map not found"); + + /* The end of the partition list is marked using "-1". */ + while (next != -1) + { + struct grub_amiga_partition apart; + + /* Read the RDSK block which is a descriptor for the entire disk. */ + if (grub_disk_read (disk, next, 0, sizeof (apart), &apart)) + return grub_errno; + + if (grub_memcmp (apart.magic, GRUB_AMIGA_PART_MAGIC, + sizeof (apart.magic)) != 0) + return grub_error (GRUB_ERR_BAD_PART_TABLE, + "invalid Amiga partition map"); + /* Calculate the first block and the size of the partition. */ + part.start = (grub_be_to_cpu32 (apart.lowcyl) + * grub_be_to_cpu32 (apart.heads) + * grub_be_to_cpu32 (apart.block_per_track)); + part.len = ((grub_be_to_cpu32 (apart.highcyl) + - grub_be_to_cpu32 (apart.lowcyl) + 1) + * grub_be_to_cpu32 (apart.heads) + * grub_be_to_cpu32 (apart.block_per_track)); + + part.offset = (grub_off_t) next * 512; + part.number = partno; + part.index = 0; + part.partmap = &grub_amiga_partition_map; + + if (hook (disk, &part)) + return grub_errno; + + next = grub_be_to_cpu32 (apart.next); + partno++; + } + + return 0; +} + + +/* Partition map type. */ +static struct grub_partition_map grub_amiga_partition_map = + { + .name = "amiga", + .iterate = amiga_partition_map_iterate, + }; + +GRUB_MOD_INIT(part_amiga) +{ + grub_partition_map_register (&grub_amiga_partition_map); +} + +GRUB_MOD_FINI(part_amiga) +{ + grub_partition_map_unregister (&grub_amiga_partition_map); +} diff --git a/grub-core/partmap/apple.c b/grub-core/partmap/apple.c new file mode 100644 index 0000000..c08cae5 --- /dev/null +++ b/grub-core/partmap/apple.c @@ -0,0 +1,199 @@ +/* apple.c - Read macintosh partition tables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define GRUB_APPLE_HEADER_MAGIC 0x4552 +#define GRUB_APPLE_PART_MAGIC 0x504D + +struct grub_apple_header +{ + /* The magic number to identify the partition map, it should have + the value `0x4552'. */ + grub_uint16_t magic; + grub_uint16_t blocksize; +}; + +struct grub_apple_part +{ + /* The magic number to identify this as a partition, it should have + the value `0x504D'. */ + grub_uint16_t magic; + + /* Reserved. */ + grub_uint16_t reserved; + + /* The size of the partition map in blocks. */ + grub_uint32_t partmap_size; + + /* The first physical block of the partition. */ + grub_uint32_t first_phys_block; + + /* The amount of blocks. */ + grub_uint32_t blockcnt; + + /* The partition name. */ + char partname[32]; + + /* The partition type. */ + char parttype[32]; + + /* The first datablock of the partition. */ + grub_uint32_t datablocks_first; + + /* The amount datablocks. */ + grub_uint32_t datablocks_count; + + /* The status of the partition. (???) */ + grub_uint32_t status; + + /* The first block on which the bootcode can be found. */ + grub_uint32_t bootcode_pos; + + /* The size of the bootcode in bytes. */ + grub_uint32_t bootcode_size; + + /* The load address of the bootcode. */ + grub_uint32_t bootcode_loadaddr; + + /* Reserved. */ + grub_uint32_t reserved2; + + /* The entry point of the bootcode. */ + grub_uint32_t bootcode_entrypoint; + + /* Reserved. */ + grub_uint32_t reserved3; + + /* A checksum of the bootcode. */ + grub_uint32_t bootcode_checksum; + + /* The processor type. */ + char processor[16]; + + /* Padding. */ + grub_uint16_t pad[187]; +}; + +static struct grub_partition_map grub_apple_partition_map; + + +static grub_err_t +apple_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + struct grub_partition part; + struct grub_apple_header aheader; + struct grub_apple_part apart; + int partno = 0, partnum = 0; + unsigned pos; + + part.partmap = &grub_apple_partition_map; + + if (grub_disk_read (disk, 0, 0, sizeof (aheader), &aheader)) + return grub_errno; + + if (grub_be_to_cpu16 (aheader.magic) != GRUB_APPLE_HEADER_MAGIC) + { + grub_dprintf ("partition", + "bad magic (found 0x%x; wanted 0x%x\n", + grub_be_to_cpu16 (aheader.magic), + GRUB_APPLE_HEADER_MAGIC); + goto fail; + } + + pos = grub_be_to_cpu16 (aheader.blocksize); + + do + { + part.offset = pos / GRUB_DISK_SECTOR_SIZE; + part.index = pos % GRUB_DISK_SECTOR_SIZE; + + if (grub_disk_read (disk, part.offset, part.index, + sizeof (struct grub_apple_part), &apart)) + return grub_errno; + + if (grub_be_to_cpu16 (apart.magic) != GRUB_APPLE_PART_MAGIC) + { + grub_dprintf ("partition", + "partition %d: bad magic (found 0x%x; wanted 0x%x\n", + partno, grub_be_to_cpu16 (apart.magic), + GRUB_APPLE_PART_MAGIC); + break; + } + + if (partnum == 0) + partnum = grub_be_to_cpu32 (apart.partmap_size); + + part.start = ((grub_disk_addr_t) grub_be_to_cpu32 (apart.first_phys_block) + * grub_be_to_cpu16 (aheader.blocksize)) + / GRUB_DISK_SECTOR_SIZE; + part.len = ((grub_disk_addr_t) grub_be_to_cpu32 (apart.blockcnt) + * grub_be_to_cpu16 (aheader.blocksize)) + / GRUB_DISK_SECTOR_SIZE; + part.offset = pos; + part.index = partno; + part.number = partno; + + grub_dprintf ("partition", + "partition %d: name %s, type %s, start 0x%x, len 0x%x\n", + partno, apart.partname, apart.parttype, + grub_be_to_cpu32 (apart.first_phys_block), + grub_be_to_cpu32 (apart.blockcnt)); + + if (hook (disk, &part)) + return grub_errno; + + pos += grub_be_to_cpu16 (aheader.blocksize); + partno++; + } + while (partno < partnum); + + if (partno != 0) + return 0; + + fail: + return grub_error (GRUB_ERR_BAD_PART_TABLE, + "Apple partition map not found"); +} + + +/* Partition map type. */ +static struct grub_partition_map grub_apple_partition_map = + { + .name = "apple", + .iterate = apple_partition_map_iterate, + }; + +GRUB_MOD_INIT(part_apple) +{ + grub_partition_map_register (&grub_apple_partition_map); +} + +GRUB_MOD_FINI(part_apple) +{ + grub_partition_map_unregister (&grub_apple_partition_map); +} + diff --git a/grub-core/partmap/bsdlabel.c b/grub-core/partmap/bsdlabel.c new file mode 100644 index 0000000..888100a --- /dev/null +++ b/grub-core/partmap/bsdlabel.c @@ -0,0 +1,254 @@ +/* bsdlabel.c - Read BSD style partition tables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#ifdef GRUB_UTIL +#include +#endif + +static struct grub_partition_map grub_bsdlabel_partition_map; +static struct grub_partition_map grub_netbsdlabel_partition_map; +static struct grub_partition_map grub_openbsdlabel_partition_map; + + + +static grub_err_t +iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd, + struct grub_partition_map *pmap, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + struct grub_partition_bsd_disk_label label; + struct grub_partition p; + grub_disk_addr_t delta = 0; + grub_disk_addr_t pos; + + /* Read the BSD label. */ + if (grub_disk_read (disk, sector, 0, sizeof (label), &label)) + return grub_errno; + + /* Check if it is valid. */ + if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); + + /* A kludge to determine a base of be.offset. */ + if (GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION + < grub_cpu_to_le16 (label.num_partitions) && freebsd) + { + struct grub_partition_bsd_entry whole_disk_be; + + pos = sizeof (label) + sector * GRUB_DISK_SECTOR_SIZE + + sizeof (struct grub_partition_bsd_entry) + * GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION; + + if (grub_disk_read (disk, pos / GRUB_DISK_SECTOR_SIZE, + pos % GRUB_DISK_SECTOR_SIZE, sizeof (whole_disk_be), + &whole_disk_be)) + return grub_errno; + + delta = grub_le_to_cpu32 (whole_disk_be.offset); + } + + pos = sizeof (label) + sector * GRUB_DISK_SECTOR_SIZE; + + for (p.number = 0; + p.number < grub_cpu_to_le16 (label.num_partitions); + p.number++, pos += sizeof (struct grub_partition_bsd_entry)) + { + struct grub_partition_bsd_entry be; + + if (p.number == GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION) + continue; + + p.offset = pos / GRUB_DISK_SECTOR_SIZE; + p.index = pos % GRUB_DISK_SECTOR_SIZE; + + if (grub_disk_read (disk, p.offset, p.index, sizeof (be), &be)) + return grub_errno; + + p.start = grub_le_to_cpu32 (be.offset); + p.len = grub_le_to_cpu32 (be.size); + p.partmap = pmap; + + if (p.len == 0) + continue; + + if (p.start < delta) + { +#ifdef GRUB_UTIL + char *partname; + /* disk->partition != NULL as 0 < delta */ + partname = disk->partition ? grub_partition_get_name (disk->partition) + : ""; + grub_util_warn ("Discarding improperly nested partition (%s,%s,%s%d)", + disk->name, partname, p.partmap->name, p.number + 1); + grub_free (partname); +#endif + continue; + } + + p.start -= delta; + + if (hook (disk, &p)) + return grub_errno; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +bsdlabel_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + + if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos") + == 0 && disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_FREEBSD) + return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 1, + &grub_bsdlabel_partition_map, hook); + + if (disk->partition + && (grub_strcmp (disk->partition->partmap->name, "msdos") == 0 + || disk->partition->partmap == &grub_bsdlabel_partition_map + || disk->partition->partmap == &grub_netbsdlabel_partition_map + || disk->partition->partmap == &grub_openbsdlabel_partition_map)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported"); + + return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, + &grub_bsdlabel_partition_map, hook); +} + +/* This is a total breakage. Even when net-/openbsd label is inside partition + it actually describes the whole disk. + */ +static grub_err_t +netopenbsdlabel_partition_map_iterate (grub_disk_t disk, grub_uint8_t type, + struct grub_partition_map *pmap, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + int count = 0; + + auto int check_msdos (grub_disk_t dsk, + const grub_partition_t partition); + + int check_msdos (grub_disk_t dsk, + const grub_partition_t partition) + { + grub_err_t err; + + if (partition->msdostype != type) + return 0; + + err = iterate_real (dsk, partition->start + + GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, pmap, hook); + if (err == GRUB_ERR_NONE) + { + count++; + return 1; + } + if (err == GRUB_ERR_BAD_PART_TABLE) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + grub_print_error (); + return 0; + } + + if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos") + == 0) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported"); + + { + grub_err_t err; + err = grub_partition_msdos_iterate (disk, check_msdos); + + if (err) + return err; + if (!count) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no bsdlabel found"); + } + return GRUB_ERR_NONE; +} + +static grub_err_t +netbsdlabel_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + return netopenbsdlabel_partition_map_iterate (disk, + GRUB_PC_PARTITION_TYPE_NETBSD, + &grub_netbsdlabel_partition_map, + hook); +} + +static grub_err_t +openbsdlabel_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + return netopenbsdlabel_partition_map_iterate (disk, + GRUB_PC_PARTITION_TYPE_OPENBSD, + &grub_openbsdlabel_partition_map, + hook); +} + + +static struct grub_partition_map grub_bsdlabel_partition_map = + { + .name = "bsd", + .iterate = bsdlabel_partition_map_iterate, + }; + +static struct grub_partition_map grub_openbsdlabel_partition_map = + { + .name = "openbsd", + .iterate = openbsdlabel_partition_map_iterate, + }; + +static struct grub_partition_map grub_netbsdlabel_partition_map = + { + .name = "netbsd", + .iterate = netbsdlabel_partition_map_iterate, + }; + + + +GRUB_MOD_INIT(part_bsd) +{ + grub_partition_map_register (&grub_bsdlabel_partition_map); + grub_partition_map_register (&grub_netbsdlabel_partition_map); + grub_partition_map_register (&grub_openbsdlabel_partition_map); +} + +GRUB_MOD_FINI(part_bsd) +{ + grub_partition_map_unregister (&grub_bsdlabel_partition_map); + grub_partition_map_unregister (&grub_netbsdlabel_partition_map); + grub_partition_map_unregister (&grub_openbsdlabel_partition_map); +} diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c new file mode 100644 index 0000000..73a1c3b --- /dev/null +++ b/grub-core/partmap/gpt.c @@ -0,0 +1,208 @@ +/* gpt.c - Read GUID Partition Tables (GPT). */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2005,2006,2007,2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_uint8_t grub_gpt_magic[8] = + { + 0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54 + }; + +static const grub_gpt_part_type_t grub_gpt_partition_type_empty = GRUB_GPT_PARTITION_TYPE_EMPTY; + +#ifdef GRUB_UTIL +static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; +#endif + +/* 512 << 7 = 65536 byte sectors. */ +#define MAX_SECTOR_LOG 7 + +static struct grub_partition_map grub_gpt_partition_map; + + + +static grub_err_t +gpt_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + struct grub_partition part; + struct grub_gpt_header gpt; + struct grub_gpt_partentry entry; + struct grub_msdos_partition_mbr mbr; + grub_uint64_t entries; + unsigned int i; + int last_offset = 0; + int sector_log = 0; + + /* Read the protective MBR. */ + if (grub_disk_read (disk, 0, 0, sizeof (mbr), &mbr)) + return grub_errno; + + /* Check if it is valid. */ + if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); + + /* Make sure the MBR is a protective MBR and not a normal MBR. */ + if (mbr.entries[0].type != GRUB_PC_PARTITION_TYPE_GPT_DISK) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no GPT partition map found"); + + /* Read the GPT header. */ + for (sector_log = 0; sector_log < MAX_SECTOR_LOG; sector_log++) + { + if (grub_disk_read (disk, 1 << sector_log, 0, sizeof (gpt), &gpt)) + return grub_errno; + + if (grub_memcmp (gpt.magic, grub_gpt_magic, sizeof (grub_gpt_magic)) == 0) + break; + } + if (sector_log == MAX_SECTOR_LOG) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no valid GPT header"); + + grub_dprintf ("gpt", "Read a valid GPT header\n"); + + entries = grub_le_to_cpu64 (gpt.partitions) << sector_log; + for (i = 0; i < grub_le_to_cpu32 (gpt.maxpart); i++) + { + if (grub_disk_read (disk, entries, last_offset, + sizeof (entry), &entry)) + return grub_errno; + + if (grub_memcmp (&grub_gpt_partition_type_empty, &entry.type, + sizeof (grub_gpt_partition_type_empty))) + { + /* Calculate the first block and the size of the partition. */ + part.start = grub_le_to_cpu64 (entry.start) << sector_log; + part.len = (grub_le_to_cpu64 (entry.end) + - grub_le_to_cpu64 (entry.start) + 1) << sector_log; + part.offset = entries; + part.number = i; + part.index = last_offset; + part.partmap = &grub_gpt_partition_map; + part.parent = disk->partition; + + grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n", i, + (unsigned long long) part.start, + (unsigned long long) part.len); + + if (hook (disk, &part)) + return grub_errno; + } + + last_offset += grub_le_to_cpu32 (gpt.partentry_size); + if (last_offset == GRUB_DISK_SECTOR_SIZE) + { + last_offset = 0; + entries++; + } + } + + return GRUB_ERR_NONE; +} + +#ifdef GRUB_UTIL +static grub_err_t +gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t **sectors) +{ + grub_disk_addr_t start = 0, len = 0; + unsigned i; + grub_err_t err; + + auto int NESTED_FUNC_ATTR find_usable_region (grub_disk_t disk, + const grub_partition_t p); + int NESTED_FUNC_ATTR find_usable_region (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) + { + struct grub_gpt_partentry gptdata; + + disk->partition = p->parent; + if (grub_disk_read (disk, p->offset, p->index, + sizeof (gptdata), &gptdata)) + return 0; + + /* If there's an embed region, it is in a dedicated partition. */ + if (! grub_memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16)) + { + start = p->start; + len = p->len; + return 1; + } + + return 0; + } + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "GPT curently supports only PC-BIOS embedding"); + + err = gpt_partition_map_iterate (disk, find_usable_region); + if (err) + return err; + + if (len == 0) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + "This GPT partition label has no BIOS Boot Partition;" + " embedding won't be possible!"); + + if (len < *nsectors) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your BIOS Boot Partition is too small;" + " embedding won't be possible!"); + + *nsectors = len; + *sectors = grub_malloc (*nsectors * sizeof (**sectors)); + if (!*sectors) + return grub_errno; + for (i = 0; i < *nsectors; i++) + (*sectors)[i] = start + i; + + return GRUB_ERR_NONE; +} +#endif + + +/* Partition map type. */ +static struct grub_partition_map grub_gpt_partition_map = + { + .name = "gpt", + .iterate = gpt_partition_map_iterate, +#ifdef GRUB_UTIL + .embed = gpt_partition_map_embed +#endif + }; + +GRUB_MOD_INIT(part_gpt) +{ + grub_partition_map_register (&grub_gpt_partition_map); +} + +GRUB_MOD_FINI(part_gpt) +{ + grub_partition_map_unregister (&grub_gpt_partition_map); +} diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c new file mode 100644 index 0000000..1b71c69 --- /dev/null +++ b/grub-core/partmap/msdos.c @@ -0,0 +1,284 @@ +/* pc.c - Read PC style partition tables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static struct grub_partition_map grub_msdos_partition_map; + + +grub_err_t +grub_partition_msdos_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + struct grub_partition p; + struct grub_msdos_partition_mbr mbr; + int labeln = 0; + grub_disk_addr_t lastaddr; + grub_disk_addr_t ext_offset; + grub_disk_addr_t delta = 0; + + if (disk->partition && disk->partition->partmap == &grub_msdos_partition_map) + { + if (disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_LINUX_MINIX) + delta = disk->partition->start; + else + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported"); + } + + p.offset = 0; + ext_offset = 0; + p.number = -1; + p.partmap = &grub_msdos_partition_map; + + /* Any value different than `p.offset' will satisfy the check during + first loop. */ + lastaddr = !p.offset; + + while (1) + { + int i; + struct grub_msdos_partition_entry *e; + + /* Read the MBR. */ + if (grub_disk_read (disk, p.offset, 0, sizeof (mbr), &mbr)) + goto finish; + + /* This is our loop-detection algorithm. It works the following way: + It saves last position which was a power of two. Then it compares the + saved value with a current one. This way it's guaranteed that the loop + will be broken by at most third walk. + */ + if (labeln && lastaddr == p.offset) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "loop detected"); + + labeln++; + if ((labeln & (labeln - 1)) == 0) + lastaddr = p.offset; + + /* Check if it is valid. */ + if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); + + for (i = 0; i < 4; i++) + if (mbr.entries[i].flag & 0x7f) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag"); + + /* Analyze DOS partitions. */ + for (p.index = 0; p.index < 4; p.index++) + { + e = mbr.entries + p.index; + + p.start = p.offset + grub_le_to_cpu32 (e->start) - delta; + p.len = grub_le_to_cpu32 (e->length); + p.msdostype = e->type; + + grub_dprintf ("partition", + "partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n", + p.index, e->flag, e->type, + (unsigned long long) p.start, + (unsigned long long) p.len); + + /* If this is a GPT partition, this MBR is just a dummy. */ + if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && p.index == 0) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr"); + + /* If this partition is a normal one, call the hook. */ + if (! grub_msdos_partition_is_empty (e->type) + && ! grub_msdos_partition_is_extended (e->type)) + { + p.number++; + + if (hook (disk, &p)) + return grub_errno; + } + else if (p.number < 4) + /* If this partition is a logical one, shouldn't increase the + partition number. */ + p.number++; + } + + /* Find an extended partition. */ + for (i = 0; i < 4; i++) + { + e = mbr.entries + i; + + if (grub_msdos_partition_is_extended (e->type)) + { + p.offset = ext_offset + grub_le_to_cpu32 (e->start); + if (! ext_offset) + ext_offset = p.offset; + + break; + } + } + + /* If no extended partition, the end. */ + if (i == 4) + break; + } + + finish: + return grub_errno; +} + +#ifdef GRUB_UTIL +static grub_err_t +pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t **sectors) +{ + grub_disk_addr_t end = ~0ULL; + struct grub_msdos_partition_mbr mbr; + int labeln = 0; + /* Any value different than `p.offset' will satisfy the check during + first loop. */ + grub_disk_addr_t lastaddr = 1; + grub_disk_addr_t ext_offset = 0; + grub_disk_addr_t offset = 0; + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "PC-style partitions curently support " + "only PC-BIOS embedding"); + + if (disk->partition) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Embedding on MSDOS subpartition isn't supported"); + + while (1) + { + int i; + struct grub_msdos_partition_entry *e; + grub_err_t err; + + /* Read the MBR. */ + err = grub_disk_read (disk, offset, 0, sizeof (mbr), &mbr); + if (err) + return err; + + /* This is our loop-detection algorithm. It works the following way: + It saves last position which was a power of two. Then it compares the + saved value with a current one. This way it's guaranteed that the loop + will be broken by at most third walk. + */ + if (labeln && lastaddr == offset) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "loop detected"); + + labeln++; + if ((labeln & (labeln - 1)) == 0) + lastaddr = offset; + + /* Check if it is valid. */ + if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); + + for (i = 0; i < 4; i++) + if (mbr.entries[i].flag & 0x7f) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag"); + + /* Analyze DOS partitions. */ + for (i = 0; i < 4; i++) + { + e = mbr.entries + i; + + if (!grub_msdos_partition_is_empty (e->type) + && end > offset + grub_le_to_cpu32 (e->start)) + end = offset + grub_le_to_cpu32 (e->start); + + /* If this is a GPT partition, this MBR is just a dummy. */ + if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr"); + } + + /* Find an extended partition. */ + for (i = 0; i < 4; i++) + { + e = mbr.entries + i; + + if (grub_msdos_partition_is_extended (e->type)) + { + offset = ext_offset + grub_le_to_cpu32 (e->start); + if (! ext_offset) + ext_offset = offset; + + break; + } + } + + /* If no extended partition, the end. */ + if (i == 4) + break; + } + + if (end >= *nsectors + 2) + { + unsigned i; + *nsectors = end - 2; + *sectors = grub_malloc (*nsectors * sizeof (**sectors)); + if (!*sectors) + return grub_errno; + for (i = 0; i < *nsectors; i++) + (*sectors)[i] = 1 + i; + return GRUB_ERR_NONE; + } + + if (end <= 1) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + "This msdos-style partition label has no " + "post-MBR gap; embedding won't be possible!"); + + if (*nsectors > 62) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your core.img is unusually large. " + "It won't fit in the embedding area."); + + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your embedding area is unusually small. " + "core.img won't fit in it."); +} +#endif + + +/* Partition map type. */ +static struct grub_partition_map grub_msdos_partition_map = + { + .name = "msdos", + .iterate = grub_partition_msdos_iterate, +#ifdef GRUB_UTIL + .embed = pc_partition_map_embed +#endif + }; + +GRUB_MOD_INIT(part_msdos) +{ + grub_partition_map_register (&grub_msdos_partition_map); +} + +GRUB_MOD_FINI(part_msdos) +{ + grub_partition_map_unregister (&grub_msdos_partition_map); +} diff --git a/grub-core/partmap/sun.c b/grub-core/partmap/sun.c new file mode 100644 index 0000000..c7ef681 --- /dev/null +++ b/grub-core/partmap/sun.c @@ -0,0 +1,151 @@ +/* sun.c - Read SUN style partition tables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2005,2006,2007 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define GRUB_PARTMAP_SUN_MAGIC 0xDABE +#define GRUB_PARTMAP_SUN_MAX_PARTS 8 +#define GRUB_PARTMAP_SUN_WHOLE_DISK_ID 0x05 + +struct grub_sun_partition_info +{ + grub_uint8_t spare1; + grub_uint8_t id; + grub_uint8_t spare2; + grub_uint8_t flags; +} __attribute__ ((packed)); + +struct grub_sun_partition_descriptor +{ + grub_uint32_t start_cylinder; + grub_uint32_t num_sectors; +} __attribute__ ((packed)); + +struct grub_sun_block +{ + grub_uint8_t info[128]; /* Informative text string. */ + grub_uint8_t spare0[14]; + struct grub_sun_partition_info infos[8]; + grub_uint8_t spare1[246]; /* Boot information etc. */ + grub_uint16_t rspeed; /* Disk rotational speed. */ + grub_uint16_t pcylcount; /* Physical cylinder count. */ + grub_uint16_t sparecyl; /* extra sects per cylinder. */ + grub_uint8_t spare2[4]; /* More magic... */ + grub_uint16_t ilfact; /* Interleave factor. */ + grub_uint16_t ncyl; /* Data cylinder count. */ + grub_uint16_t nacyl; /* Alt. cylinder count. */ + grub_uint16_t ntrks; /* Tracks per cylinder. */ + grub_uint16_t nsect; /* Sectors per track. */ + grub_uint8_t spare3[4]; /* Even more magic... */ + struct grub_sun_partition_descriptor partitions[8]; + grub_uint16_t magic; /* Magic number. */ + grub_uint16_t csum; /* Label xor'd checksum. */ +} __attribute__ ((packed)); + +static struct grub_partition_map grub_sun_partition_map; + +/* Verify checksum (true=ok). */ +static int +grub_sun_is_valid (struct grub_sun_block *label) +{ + grub_uint16_t *pos; + grub_uint16_t sum = 0; + + for (pos = (grub_uint16_t *) label; + pos < (grub_uint16_t *) (label + 1); + pos++) + sum ^= *pos; + + return ! sum; +} + +static grub_err_t +sun_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + struct grub_partition p; + struct grub_sun_block block; + int partnum; + grub_err_t err; + + p.partmap = &grub_sun_partition_map; + err = grub_disk_read (disk, 0, 0, sizeof (struct grub_sun_block), + &block); + if (err) + return err; + + if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); + + if (! grub_sun_is_valid (&block)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); + + /* Maybe another error value would be better, because partition + table _is_ recognized but invalid. */ + for (partnum = 0; partnum < GRUB_PARTMAP_SUN_MAX_PARTS; partnum++) + { + struct grub_sun_partition_descriptor *desc; + + if (block.infos[partnum].id == 0 + || block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID) + continue; + + desc = &block.partitions[partnum]; + p.start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) + * grub_be_to_cpu16 (block.ntrks) + * grub_be_to_cpu16 (block.nsect)); + p.len = grub_be_to_cpu32 (desc->num_sectors); + p.number = p.index = partnum; + if (p.len) + { + if (hook (disk, &p)) + partnum = GRUB_PARTMAP_SUN_MAX_PARTS; + } + } + + return grub_errno; +} + +/* Partition map type. */ +static struct grub_partition_map grub_sun_partition_map = + { + .name = "sun", + .iterate = sun_partition_map_iterate, + }; + +GRUB_MOD_INIT(part_sun) +{ + grub_partition_map_register (&grub_sun_partition_map); +} + +GRUB_MOD_FINI(part_sun) +{ + grub_partition_map_unregister (&grub_sun_partition_map); +} + diff --git a/grub-core/partmap/sunpc.c b/grub-core/partmap/sunpc.c new file mode 100644 index 0000000..28dc4f5 --- /dev/null +++ b/grub-core/partmap/sunpc.c @@ -0,0 +1,146 @@ +/* sunpc.c - Read SUN PC style partition tables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2005,2006,2007,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define GRUB_PARTMAP_SUN_PC_MAGIC 0xDABE +#define GRUB_PARTMAP_SUN_PC_MAX_PARTS 16 +#define GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID 0x05 + +struct grub_sun_pc_partition_descriptor +{ + grub_uint16_t id; + grub_uint16_t unused; + grub_uint32_t start_sector; + grub_uint32_t num_sectors; +} __attribute__ ((packed)); + +struct grub_sun_pc_block +{ + grub_uint8_t unused[72]; + struct grub_sun_pc_partition_descriptor partitions[GRUB_PARTMAP_SUN_PC_MAX_PARTS]; + grub_uint8_t unused2[244]; + grub_uint16_t magic; /* Magic number. */ + grub_uint16_t csum; /* Label xor'd checksum. */ +} __attribute__ ((packed)); + +static struct grub_partition_map grub_sun_pc_partition_map; + +/* Verify checksum (true=ok). */ +static int +grub_sun_is_valid (struct grub_sun_pc_block *label) +{ + grub_uint16_t *pos; + grub_uint16_t sum = 0; + + for (pos = (grub_uint16_t *) label; + pos < (grub_uint16_t *) (label + 1); + pos++) + sum ^= *pos; + + return ! sum; +} + +static grub_err_t +sun_pc_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + grub_partition_t p; + struct grub_sun_pc_block block; + int partnum; + grub_err_t err; + + p = (grub_partition_t) grub_zalloc (sizeof (struct grub_partition)); + if (! p) + return grub_errno; + + p->partmap = &grub_sun_pc_partition_map; + err = grub_disk_read (disk, 1, 0, sizeof (struct grub_sun_pc_block), &block); + if (err) + { + grub_free (p); + return err; + } + + if (GRUB_PARTMAP_SUN_PC_MAGIC != grub_le_to_cpu16 (block.magic)) + { + grub_free (p); + return grub_error (GRUB_ERR_BAD_PART_TABLE, + "not a sun_pc partition table"); + } + + if (! grub_sun_is_valid (&block)) + { + grub_free (p); + return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); + } + + /* Maybe another error value would be better, because partition + table _is_ recognized but invalid. */ + for (partnum = 0; partnum < GRUB_PARTMAP_SUN_PC_MAX_PARTS; partnum++) + { + struct grub_sun_pc_partition_descriptor *desc; + + if (block.partitions[partnum].id == 0 + || block.partitions[partnum].id == GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID) + continue; + + desc = &block.partitions[partnum]; + p->start = grub_le_to_cpu32 (desc->start_sector); + p->len = grub_le_to_cpu32 (desc->num_sectors); + p->number = partnum; + if (p->len) + { + if (hook (disk, p)) + partnum = GRUB_PARTMAP_SUN_PC_MAX_PARTS; + } + } + + grub_free (p); + + return grub_errno; +} + +/* Partition map type. */ +static struct grub_partition_map grub_sun_pc_partition_map = + { + .name = "sunpc", + .iterate = sun_pc_partition_map_iterate, + }; + +GRUB_MOD_INIT(part_sunpc) +{ + grub_partition_map_register (&grub_sun_pc_partition_map); +} + +GRUB_MOD_FINI(part_sunpc) +{ + grub_partition_map_unregister (&grub_sun_pc_partition_map); +} + -- cgit v1.2.3