1 /* sunpc.c - Read SUN PC style partition tables. */ 2 /* 3 * GRUB -- GRand Unified Bootloader 4 * Copyright (C) 2002,2005,2006,2007,2009 Free Software Foundation, Inc. 5 * 6 * GRUB 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 3 of the License, or 9 * (at your option) any later version. 10 * 11 * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include <grub/partition.h> 21 #include <grub/disk.h> 22 #include <grub/mm.h> 23 #include <grub/misc.h> 24 #include <grub/dl.h> 25 #include <grub/symbol.h> 26 #include <grub/types.h> 27 #include <grub/err.h> 28 29 GRUB_MOD_LICENSE ("GPLv3+"); 30 31 #define GRUB_PARTMAP_SUN_PC_MAGIC 0xDABE 32 #define GRUB_PARTMAP_SUN_PC_MAX_PARTS 16 33 #define GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID 0x05 34 35 struct grub_sun_pc_partition_descriptor 36 { 37 grub_uint16_t id; 38 grub_uint16_t unused; 39 grub_uint32_t start_sector; 40 grub_uint32_t num_sectors; 41 } __attribute__ ((packed)); 42 43 struct grub_sun_pc_block 44 { 45 grub_uint8_t unused[72]; 46 struct grub_sun_pc_partition_descriptor partitions[GRUB_PARTMAP_SUN_PC_MAX_PARTS]; 47 grub_uint8_t unused2[244]; 48 grub_uint16_t magic; /* Magic number. */ 49 grub_uint16_t csum; /* Label xor'd checksum. */ 50 } __attribute__ ((packed)); 51 52 static struct grub_partition_map grub_sun_pc_partition_map; 53 54 /* Verify checksum (true=ok). */ 55 static int 56 grub_sun_is_valid (grub_uint16_t *label) 57 { 58 grub_uint16_t *pos; 59 grub_uint16_t sum = 0; 60 61 for (pos = label; 62 pos < (label + sizeof (struct grub_sun_pc_block) / 2); 63 pos++) 64 sum ^= *pos; 65 66 return ! sum; 67 } 68 69 static grub_err_t 70 sun_pc_partition_map_iterate (grub_disk_t disk, 71 int (*hook) (grub_disk_t disk, 72 const grub_partition_t partition)) 73 { 74 grub_partition_t p; 75 union 76 { 77 struct grub_sun_pc_block sunb; 78 grub_uint16_t raw[0]; 79 } block; 80 int partnum; 81 grub_err_t err; 82 83 p = (grub_partition_t) grub_zalloc (sizeof (struct grub_partition)); 84 if (! p) 85 return grub_errno; 86 87 p->partmap = &grub_sun_pc_partition_map; 88 err = grub_disk_read (disk, 1, 0, sizeof (struct grub_sun_pc_block), &block); 89 if (err) 90 { 91 grub_free (p); 92 return err; 93 } 94 95 if (GRUB_PARTMAP_SUN_PC_MAGIC != grub_le_to_cpu16 (block.sunb.magic)) 96 { 97 grub_free (p); 98 return grub_error (GRUB_ERR_BAD_PART_TABLE, 99 "not a sun_pc partition table"); 100 } 101 102 if (! grub_sun_is_valid (block.raw)) 103 { 104 grub_free (p); 105 return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); 106 } 107 108 /* Maybe another error value would be better, because partition 109 table _is_ recognized but invalid. */ 110 for (partnum = 0; partnum < GRUB_PARTMAP_SUN_PC_MAX_PARTS; partnum++) 111 { 112 struct grub_sun_pc_partition_descriptor *desc; 113 114 if (block.sunb.partitions[partnum].id == 0 115 || block.sunb.partitions[partnum].id 116 == GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID) 117 continue; 118 119 desc = &block.sunb.partitions[partnum]; 120 p->start = grub_le_to_cpu32 (desc->start_sector); 121 p->len = grub_le_to_cpu32 (desc->num_sectors); 122 p->number = partnum; 123 if (p->len) 124 { 125 if (hook (disk, p)) 126 partnum = GRUB_PARTMAP_SUN_PC_MAX_PARTS; 127 } 128 } 129 130 grub_free (p); 131 132 return grub_errno; 133 } 134 135 /* Partition map type. */ 136 static struct grub_partition_map grub_sun_pc_partition_map = 137 { 138 .name = "sunpc", 139 .iterate = sun_pc_partition_map_iterate, 140 }; 141 142 GRUB_MOD_INIT(part_sunpc) 143 { 144 grub_partition_map_register (&grub_sun_pc_partition_map); 145 } 146 147 GRUB_MOD_FINI(part_sunpc) 148 { 149 grub_partition_map_unregister (&grub_sun_pc_partition_map); 150 } 151