2 * Copyright (c) 2003 Marcel Moolenaar
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/types.h>
31 #include <sys/disklabel.h>
32 #include <sys/diskmbr.h>
47 static uuid_t _efi = GPT_ENT_TYPE_EFI;
48 static uuid_t _mbr = GPT_ENT_TYPE_MBR;
49 static uuid_t _fbsd = GPT_ENT_TYPE_FREEBSD;
50 static uuid_t _swap = GPT_ENT_TYPE_FREEBSD_SWAP;
51 static uuid_t _ufs = GPT_ENT_TYPE_FREEBSD_UFS;
54 parse_disk(char *conftxt, const char *name)
58 struct dos_partition *part;
63 disk = (struct disk *)calloc(sizeof *disk, 1);
67 disk->name = strdup(name);
68 p = strsep(&conftxt, " "); /* media size */
69 disk->media_size = strtoimax(p, &q, 0);
73 p = strsep(&conftxt, " "); /* sector size */
74 disk->sector_size = strtoul(p, &q, 0);
78 if (disk->sector_size == 0)
79 disk->sector_size = 512;
81 if (disk->media_size % disk->sector_size)
85 * We need to read the disk to get GPT specific information.
88 snprintf(devname, sizeof(devname), "%s%s", _PATH_DEV, name);
89 fd = open(devname, O_RDONLY);
92 buffer = malloc(2 * disk->sector_size);
97 if (read(fd, buffer, 2 * disk->sector_size) == -1) {
104 gpt = (struct gpt_hdr *)(buffer + disk->sector_size);
105 if (memcmp(gpt->hdr_sig, GPT_HDR_SIG, sizeof(gpt->hdr_sig))) {
107 * No GPT present. Check if the MBR is empty (if present)
108 * or is a PMBR before declaring this disk as empty. If
109 * the MBR isn't empty, bail out. Let's not risk nuking a
112 if (*(u_short *)(buffer + DOSMAGICOFFSET) == DOSMAGIC) {
113 for (i = 0; i < 4; i++) {
114 part = (struct dos_partition *)
115 (buffer + DOSPARTOFF + i * DOSPARTSIZE);
116 if (part->dp_typ != 0 &&
117 part->dp_typ != DOSPTYP_PMBR)
125 disk->gpt_size = 128;
126 disk->lba_start = (disk->gpt_size * sizeof(struct gpt_ent)) /
127 disk->sector_size + 2;
128 disk->lba_end = (disk->media_size / disk->sector_size) -
131 disk->lba_start = gpt->hdr_lba_start;
132 disk->lba_end = gpt->hdr_lba_end;
133 disk->gpt_size = gpt->hdr_entries;
136 Add_Chunk(disk, disk->lba_start, disk->lba_end - disk->lba_start + 1,
137 name, whole, 0, 0, "-");
147 Int_Open_Disk(const char *name, char *conftxt)
152 char *p, *q, *r, *s, *sd, *type;
157 while (p != NULL && *p != 0) {
159 if (strcmp(q, "0") == 0) {
161 if (strcmp(q, "DISK") == 0) {
163 if (strcmp(q, name) == 0)
168 if (p != NULL && *p == '\n')
172 if (p == NULL || *p == 0)
175 conftxt = strchr(p, '\n');
179 disk = parse_disk(p, name);
183 while (conftxt != NULL && *conftxt != 0) {
185 conftxt = strchr(p, '\n');
189 sd = strsep(&p, " "); /* depth */
190 if (strcmp(sd, "0") == 0)
193 type = strsep(&p, " "); /* type */
194 chunk.name = strsep(&p, " "); /* name */
195 q = strsep(&p, " "); /* length */
196 i = strtoimax(q, &r, 0);
199 chunk.end = i / disk->sector_size;
200 q = strsep(&p, " "); /* sector size */
207 i = strtoimax(r, &s, 0);
209 uuid_from_string(r, &uuid, &status);
210 if (status != uuid_s_ok)
213 status = uuid_s_invalid_string_uuid;
215 chunk.offset = i / disk->sector_size;
216 else if (!strcmp(q, "i"))
217 chunk.flags = CHUNK_ITOF(i) | CHUNK_HAS_INDEX;
218 else if (!strcmp(q, "ty"))
222 if (strncmp(type, "MBR", 3) == 0) {
223 switch (chunk.subtype) {
225 chunk.type = freebsd;
242 } else if (strcmp(type, "BSD") == 0) {
244 } else if (strcmp(type, "GPT") == 0) {
246 if (status != uuid_s_ok)
248 if (uuid_is_nil(&uuid, NULL))
250 else if (uuid_equal(&uuid, &_efi, NULL))
252 else if (uuid_equal(&uuid, &_mbr, NULL))
254 else if (uuid_equal(&uuid, &_fbsd, NULL)) {
255 chunk.type = freebsd;
256 chunk.subtype = 0xa5;
257 } else if (uuid_equal(&uuid, &_swap, NULL)) {
259 chunk.subtype = FS_SWAP;
260 } else if (uuid_equal(&uuid, &_ufs, NULL)) {
262 chunk.subtype = FS_BSDFFS;
268 Add_Chunk(disk, chunk.offset, chunk.end, chunk.name,
269 chunk.type, chunk.subtype, chunk.flags, 0);