Merge branch 'makefile' into haiku
[grub2/phcoder.git] / partmap / pc.c
blobb195087e754bc5e24d84e074b8d50bb3707d11e3
1 /* pc.c - Read PC style partition tables. */
2 /*
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>
23 #include <grub/mm.h>
24 #include <grub/misc.h>
25 #include <grub/dl.h>
27 static struct grub_partition_map grub_pc_partition_map;
30 static grub_err_t
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));
40 p.offset = 0;
41 pcdata->ext_offset = 0;
42 p.data = pcdata;
43 p.number = -1;
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. */
48 if (disk->partition)
50 grub_free (pcdata);
51 return grub_error (GRUB_ERR_BAD_PART_TABLE,
52 "pc partition can't be nested");
55 while (1)
57 int i;
58 struct grub_pc_partition_entry *e;
60 /* Read the MBR. */
61 if (grub_disk_read (disk, p.offset, 0, sizeof (mbr), &mbr))
62 goto finish;
64 /* Check if it is valid. */
65 if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
67 grub_free (pcdata);
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)
89 grub_free (pcdata);
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))
97 p.number++;
99 if (hook (disk, &p))
100 return 1;
102 else if (p.number < 4)
103 /* If this partition is a logical one, shouldn't increase the
104 partition number. */
105 p.number++;
108 /* Find an extended partition. */
109 for (i = 0; i < 4; i++)
111 e = mbr.entries + 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;
119 break;
123 /* If no extended partition, the end. */
124 if (i == 4)
125 break;
128 finish:
129 grub_free (pcdata);
130 return grub_errno;
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);