1 /* pc.c - Read PC style partition tables. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2002,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
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.
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.
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/>.
20 #include <grub/partition.h>
21 #include <grub/pc_partition.h>
22 #include <grub/disk.h>
24 #include <grub/misc.h>
27 static struct grub_partition_map grub_pc_partition_map
;
31 pc_partition_map_iterate (grub_disk_t disk
,
32 int (*hook
) (grub_disk_t disk
,
33 const grub_partition_t partition
))
35 struct grub_partition p
;
36 struct grub_pc_partition
*pcdata
;
37 struct grub_pc_partition_mbr mbr
;
39 pcdata
= grub_malloc (sizeof (*pcdata
));
41 pcdata
->ext_offset
= 0;
44 p
.partmap
= &grub_pc_partition_map
;
46 /* Signature check is known to cause false positives
47 because the same signature is used for bootsectors. */
51 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
52 "pc partition can't be nested");
58 struct grub_pc_partition_entry
*e
;
61 if (grub_disk_read (disk
, p
.offset
, 0, sizeof (mbr
), &mbr
))
64 /* Check if it is valid. */
65 if (mbr
.signature
!= grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE
))
68 return grub_error (GRUB_ERR_BAD_PART_TABLE
, "no signature");
71 /* Analyze DOS partitions. */
72 for (pcdata
->index
= 0; pcdata
->index
< 4; pcdata
->index
++)
74 e
= mbr
.entries
+ pcdata
->index
;
76 p
.start
= p
.offset
+ grub_le_to_cpu32 (e
->start
);
77 p
.len
= grub_le_to_cpu32 (e
->length
);
78 pcdata
->dos_type
= e
->type
;
80 grub_dprintf ("partition",
81 "partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n",
82 pcdata
->index
, e
->flag
, pcdata
->dos_type
,
83 (unsigned long long) p
.start
,
84 (unsigned long long) p
.len
);
86 /* If this is a GPT partition, this MBR is just a dummy. */
87 if (e
->type
== GRUB_PC_PARTITION_TYPE_GPT_DISK
&& pcdata
->index
== 0)
90 return grub_error (GRUB_ERR_BAD_PART_TABLE
, "dummy mbr");
93 /* If this partition is a normal one, call the hook. */
94 if (! grub_pc_partition_is_empty (e
->type
)
95 && ! grub_pc_partition_is_extended (e
->type
))
102 else if (p
.number
< 4)
103 /* If this partition is a logical one, shouldn't increase the
108 /* Find an extended partition. */
109 for (i
= 0; i
< 4; i
++)
113 if (grub_pc_partition_is_extended (e
->type
))
115 p
.offset
= pcdata
->ext_offset
+ grub_le_to_cpu32 (e
->start
);
116 if (! pcdata
->ext_offset
)
117 pcdata
->ext_offset
= p
.offset
;
123 /* If no extended partition, the end. */
134 /* Partition map type. */
135 static struct grub_partition_map grub_pc_partition_map
=
137 .name
= "pc_partition_map",
138 .iterate
= pc_partition_map_iterate
,
141 GRUB_MOD_INIT(pc_partition_map
)
143 grub_partition_map_register (&grub_pc_partition_map
);
146 GRUB_MOD_FINI(pc_partition_map
)
148 grub_partition_map_unregister (&grub_pc_partition_map
);