3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * GPT (GUID Partition Table) signature detection. Based on libparted and
21 * Warning: this code doesn't do all GPT checks (CRC32, Protective MBR, ..).
22 * It's really GPT signature detection only.
24 * Copyright (C) 2007 Karel Zak <kzak@redhat.com>
33 #include <sys/ioctl.h>
34 #include <sys/utsname.h>
35 #include <sys/types.h>
44 #define GPT_HEADER_SIGNATURE 0x5452415020494645LL
45 #define GPT_PRIMARY_PARTITION_TABLE_LBA 1
50 uint16_t time_hi_and_version;
51 uint8_t clock_seq_hi_and_reserved;
52 uint8_t clock_seq_low;
54 } /* __attribute__ ((packed)) */ efi_guid_t;
55 /* commented out "__attribute__ ((packed))" to work around gcc bug (fixed
56 * in gcc3.1): __attribute__ ((packed)) breaks addressing on initialized
57 * data. It turns out we don't need it in this case, so it doesn't break
61 typedef struct _GuidPartitionTableHeader_t {
68 uint64_t AlternateLBA;
69 uint64_t FirstUsableLBA;
70 uint64_t LastUsableLBA;
72 uint64_t PartitionEntryLBA;
73 uint32_t NumberOfPartitionEntries;
74 uint32_t SizeOfPartitionEntry;
75 uint32_t PartitionEntryArrayCRC32;
76 uint8_t Reserved2[512 - 92];
77 } __attribute__ ((packed)) GuidPartitionTableHeader_t;
80 _get_sector_size (int fd)
84 if (blkdev_get_sector_size(fd, §or_size) == -1)
85 return DEFAULT_SECTOR_SIZE;
90 _get_num_sectors(int fd)
92 unsigned long long bytes=0;
94 if (blkdev_get_size(fd, &bytes) == -1)
96 return bytes / _get_sector_size(fd);
103 uint64_t sectors = 0;
106 memset(&s, 0, sizeof (s));
110 fprintf(stderr, "last_lba() could not stat: %s\n",
114 if (S_ISBLK(s.st_mode))
115 sectors = _get_num_sectors(fd);
116 else if (S_ISREG(s.st_mode))
117 sectors = s.st_size >> _get_sector_size(fd);
121 "last_lba(): I don't know how to handle files with mode %o\n",
129 read_lba(int fd, uint64_t lba, void *buffer, size_t bytes)
131 int sector_size = _get_sector_size(fd);
132 off_t offset = lba * sector_size;
134 lseek(fd, offset, SEEK_SET);
135 return read(fd, buffer, bytes);
138 static GuidPartitionTableHeader_t *
139 alloc_read_gpt_header(int fd, uint64_t lba)
141 GuidPartitionTableHeader_t *gpt =
142 (GuidPartitionTableHeader_t *) malloc(sizeof (GuidPartitionTableHeader_t));
145 memset(gpt, 0, sizeof (*gpt));
146 if (!read_lba(fd, lba, gpt, sizeof (GuidPartitionTableHeader_t)))
155 gpt_check_signature(int fd, uint64_t lba)
157 GuidPartitionTableHeader_t *gpt;
160 if ((gpt = alloc_read_gpt_header(fd, lba)))
162 if (gpt->Signature == cpu_to_le64(GPT_HEADER_SIGNATURE))
171 * 1 for valid primary GPT header
172 * 2 for valid alternative GPT header
175 gpt_probe_signature_fd(int fd)
179 /* check primary GPT header */
180 if (gpt_check_signature(fd, GPT_PRIMARY_PARTITION_TABLE_LBA))
184 /* check alternative GPT header */
185 uint64_t lastlba = last_lba(fd);
186 if (gpt_check_signature(fd, lastlba))
193 gpt_probe_signature_devname(char *devname)
196 if ((fd = open(devname, O_RDONLY)) < 0)
198 res = gpt_probe_signature_fd(fd);
205 main(int argc, char **argv)
209 fprintf(stderr, "usage: %s <dev>\n", argv[0]);
212 if (gpt_probe_signature_devname(argv[1]))
213 printf("GPT (GUID Partition Table) detected on %s\n", argv[1]);