4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * 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 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 #include <nbdkit-plugin.h>
44 #include "ascii-ctype.h"
45 #include "byte-swapping.h"
48 #include "efi-crc32.h"
51 #include "virtual-disk.h"
53 static void create_gpt_partition_header (const void *pt
, bool is_primary
,
55 static void create_gpt_partition_table (unsigned char *out
);
56 static void create_gpt_partition_table_entry (const struct region
*region
,
58 char partition_type_guid
[16],
60 static void create_gpt_protective_mbr (unsigned char *out
);
63 create_gpt_layout (void)
67 /* Protective MBR. LBA 0 */
68 create_gpt_protective_mbr (primary
);
70 /* Primary partition table. LBA 2-(LBAs+1) */
71 pt
= &primary
[2*SECTOR_SIZE
];
72 create_gpt_partition_table (pt
);
74 /* Partition table header. LBA 1 */
75 create_gpt_partition_header (pt
, true, &primary
[SECTOR_SIZE
]);
77 /* Backup partition table. LBA -(LBAs+2) */
79 create_gpt_partition_table (pt
);
81 /* Backup partition table header. LBA -1 */
82 create_gpt_partition_header (pt
, false, &secondary
[GPT_PTA_LBAs
*SECTOR_SIZE
]);
86 create_gpt_partition_header (const void *pt
, bool is_primary
,
90 struct gpt_header
*header
= (struct gpt_header
*) out
;
92 nr_lbas
= virtual_size (&the_regions
) / SECTOR_SIZE
;
94 memset (header
, 0, sizeof *header
);
95 memcpy (header
->signature
, GPT_SIGNATURE
, sizeof (header
->signature
));
96 memcpy (header
->revision
, GPT_REVISION
, sizeof (header
->revision
));
97 header
->header_size
= htole32 (sizeof *header
);
99 header
->current_lba
= htole64 (1);
100 header
->backup_lba
= htole64 (nr_lbas
- 1);
103 header
->current_lba
= htole64 (nr_lbas
- 1);
104 header
->backup_lba
= htole64 (1);
106 header
->first_usable_lba
= htole64 (2 + GPT_PTA_LBAs
);
107 header
->last_usable_lba
= htole64 (nr_lbas
- GPT_PTA_LBAs
- 2);
109 header
->partition_entries_lba
= htole64 (2);
111 header
->partition_entries_lba
= htole64 (nr_lbas
- GPT_PTA_LBAs
- 1);
112 header
->nr_partition_entries
= htole32 (GPT_PTA_SIZE
);
113 header
->size_partition_entry
= htole32 (GPT_PT_ENTRY_SIZE
);
114 header
->crc_partitions
=
115 htole32 (efi_crc32 (pt
, GPT_PT_ENTRY_SIZE
* GPT_PTA_SIZE
));
117 /* Must be computed last. */
118 header
->crc
= htole32 (efi_crc32 (header
, sizeof *header
));
122 create_gpt_partition_table (unsigned char *out
)
126 for (j
= 0; j
< nr_regions (&the_regions
); ++j
) {
127 const struct region
*region
= &the_regions
.ptr
[j
];
129 if (region
->type
== region_file
) {
131 assert (i
< GPT_PTA_SIZE
);
132 create_gpt_partition_table_entry (region
, i
== 0,
133 the_files
.ptr
[i
].type_guid
,
135 out
+= GPT_PT_ENTRY_SIZE
;
141 create_gpt_partition_table_entry (const struct region
*region
,
143 char partition_type_guid
[16],
147 const char *filename
;
148 struct gpt_entry
*entry
= (struct gpt_entry
*) out
;
150 assert (sizeof (struct gpt_entry
) == GPT_PT_ENTRY_SIZE
);
152 memcpy (entry
->partition_type_guid
, partition_type_guid
, 16);
154 memcpy (entry
->unique_guid
, the_files
.ptr
[region
->u
.i
].guid
, 16);
156 entry
->first_lba
= htole64 (region
->start
/ SECTOR_SIZE
);
157 entry
->last_lba
= htole64 (region
->end
/ SECTOR_SIZE
);
158 entry
->attributes
= htole64 (bootable
? 4 : 0);
160 /* If the filename is 7 bit ASCII then this will reproduce it as a
163 * Is this a security risk? It reveals something about paths on the
164 * server to clients. XXX
166 filename
= the_files
.ptr
[region
->u
.i
].filename
;
167 len
= strlen (filename
);
169 for (i
= 0; i
< len
; ++i
)
170 if ((unsigned char) filename
[i
] > 127)
173 for (i
= 0; i
< len
; ++i
) {
174 entry
->name
[2*i
] = filename
[i
];
175 entry
->name
[2*i
+1] = 0;
182 create_gpt_protective_mbr (unsigned char *out
)
184 struct region region
;
187 /* Protective MBR creates a partition with partition ID 0xee which
188 * covers the whole of the disk, or as much of the disk as
189 * expressible with MBR.
192 end
= virtual_size (&the_regions
) - 1;
193 if (end
> UINT32_MAX
* SECTOR_SIZE
)
194 end
= UINT32_MAX
* SECTOR_SIZE
;
196 region
.len
= region
.end
- region
.start
+ 1;
198 create_mbr_partition_table_entry (®ion
, false, 0xee, &out
[0x1be]);
200 /* Boot signature. */
205 /* Try to parse a GPT GUID. */
207 parse_guid (const char *str
, char *out
)
210 size_t len
= strlen (str
);
214 else if (len
== 38 && str
[0] == '{' && str
[37] == '}') {
223 if (str
[8] != '-' || str
[13] != '-' || str
[18] != '-' || str
[23] != '-')
226 for (i
= 0; i
< 8; ++i
)
227 if (!ascii_isxdigit (str
[i
]))
229 for (i
= 9; i
< 13; ++i
)
230 if (!ascii_isxdigit (str
[i
]))
232 for (i
= 14; i
< 18; ++i
)
233 if (!ascii_isxdigit (str
[i
]))
235 for (i
= 19; i
< 23; ++i
)
236 if (!ascii_isxdigit (str
[i
]))
238 for (i
= 24; i
< 36; ++i
)
239 if (!ascii_isxdigit (str
[i
]))
242 /* The first, second and third blocks are parsed as little endian,
243 * while the fourth and fifth blocks are big endian.
245 *out
++ = hexbyte (str
[6], str
[7]); /* first block */
246 *out
++ = hexbyte (str
[4], str
[5]);
247 *out
++ = hexbyte (str
[2], str
[3]);
248 *out
++ = hexbyte (str
[0], str
[1]);
250 *out
++ = hexbyte (str
[11], str
[12]); /* second block */
251 *out
++ = hexbyte (str
[9], str
[10]);
253 *out
++ = hexbyte (str
[16], str
[17]); /* third block */
254 *out
++ = hexbyte (str
[14], str
[15]);
256 *out
++ = hexbyte (str
[19], str
[20]); /* fourth block */
257 *out
++ = hexbyte (str
[21], str
[22]);
259 *out
++ = hexbyte (str
[24], str
[25]); /* fifth block */
260 *out
++ = hexbyte (str
[26], str
[27]);
261 *out
++ = hexbyte (str
[28], str
[29]);
262 *out
++ = hexbyte (str
[30], str
[31]);
263 *out
++ = hexbyte (str
[32], str
[33]);
264 *out
++ = hexbyte (str
[34], str
[35]);