File nyangpt.c added (mode: 100644) (index 0000000..7cfb258) |
|
1 |
|
#ifndef NYANGPT_C |
|
2 |
|
#define NYANGPT_C |
|
3 |
|
/* |
|
4 |
|
* Copyright 2021 Sylvain BERTRAND <sylvain.bertrand@legeek.net> |
|
5 |
|
* LICENSE: GNU AFFERO GPLV3 |
|
6 |
|
* (NO WARANTY OF ANY KIND AND BLAHBLAHBLAH) |
|
7 |
|
*/ |
|
8 |
|
|
|
9 |
|
/* quick and dirty, minimal, line input oriented uefi gpt partition creator */ |
|
10 |
|
|
|
11 |
|
/* |
|
12 |
|
* TODO: |
|
13 |
|
* - implement ANSI terminal pagination (listing of entries and types) |
|
14 |
|
* - utf8 to utf16 converter for names (no iconv) |
|
15 |
|
*/ |
|
16 |
|
#include <stdarg.h> |
|
17 |
|
#include <stdbool.h> |
|
18 |
|
#include <stdio.h> |
|
19 |
|
#include <string.h> |
|
20 |
|
#include <stdlib.h> |
|
21 |
|
#include <fcntl.h> |
|
22 |
|
#include <unistd.h> |
|
23 |
|
#include <sys/stat.h> |
|
24 |
|
#include <stdint.h> |
|
25 |
|
#include <inttypes.h> |
|
26 |
|
#include <endian.h> |
|
27 |
|
#include <errno.h> |
|
28 |
|
/* |
|
29 |
|
* how to get pertinent device information from sysfs for gpt partitioning |
|
30 |
|
* |
|
31 |
|
* for a /dev/sdX block device: |
|
32 |
|
* /sys/block/sdX/size = size of the device in blocks of 512 bytes (hardcoded) |
|
33 |
|
* /sys/block/sdX/queue/logical_block_size = size in bytes of a logical block |
|
34 |
|
* which is the size used by lba (Logical Block Access) offsets used |
|
35 |
|
* in gpt partitions |
|
36 |
|
* /sys/block/sdX/queue/physical_block_size = size in bytes of a physical block |
|
37 |
|
*/ |
|
38 |
|
/*{{{ global preprocessor definitions */ |
|
39 |
|
#define STATIC static |
|
40 |
|
#define utf8 uint8_t |
|
41 |
|
#define utf16 uint16_t |
|
42 |
|
#define X64_UTF8_BYTES_MAX (sizeof("18446744073709551615") - 1) |
|
43 |
|
/* meh... */ |
|
44 |
|
#define strtou64 strtoul |
|
45 |
|
#define u8 uint8_t |
|
46 |
|
#define u16 uint16_t |
|
47 |
|
#define u32 uint32_t |
|
48 |
|
#define s32 int32_t |
|
49 |
|
#define u64 uint64_t |
|
50 |
|
#define loop for(;;) |
|
51 |
|
#define ARRAY_N(x) (sizeof(x) / sizeof(x[0])) |
|
52 |
|
/*}}} global preprocessor definitions -- end */ |
|
53 |
|
/*{{{ nyangpt namespace */ |
|
54 |
|
#define blk_dev nyangpt_blk_dev |
|
55 |
|
#define build_data_from_previous_gpt nyangpt_data_from_previous_gpt |
|
56 |
|
#define change_disk_guid_prompt nyangpt_change_disk_guid_prompt |
|
57 |
|
#define colors_on nyangpt_colors_on |
|
58 |
|
#define delete_entry_prompt nyangpt_delete_entry_prompt |
|
59 |
|
#define edit_entry nyangpt_edit_entry |
|
60 |
|
#define edit_entry_attrs_prompt nyangpt_edit_entry_attrs_prompt |
|
61 |
|
#define edit_entry_first_lba_prompt nyangpt_edit_entry_first_lba_prompt |
|
62 |
|
#define edit_entry_last_lba_prompt nyangpt_edit_entry_last_lba_prompt |
|
63 |
|
#define edit_entry_prompt nyangpt_edit_entry_prompt |
|
64 |
|
#define edit_entry_to_entries nyangpt_edit_entry_to_entries |
|
65 |
|
#define edit_entry_type_prompt nyangpt_edit_entry_type_prompt |
|
66 |
|
#define edit_entry_uniq_guid_prompt nyangpt_edit_entry_uniq_guid_prompt |
|
67 |
|
#define entries nyangpt_entries |
|
68 |
|
#define entries_lbas_n nyangpt_entries_lbas_n |
|
69 |
|
#define entries_load nyangpt_entries_load |
|
70 |
|
#define entries_n nyangpt_entries_n |
|
71 |
|
#define entries_reset nyangpt_entries_reset |
|
72 |
|
#define entries_serialized_array nyangpt_entries_serialized_array |
|
73 |
|
#define entries_serialized_array_crc32 nyangpt_entries_serialized_array_crc32 |
|
74 |
|
#define entries_serialized_array_gen nyangpt_entries_serialized_array_gen |
|
75 |
|
#define entries_serialized_array_gen_entry nyangpt_entries_serialized_array_gen_entry |
|
76 |
|
#define entries_serialized_array_primary_write nyangpt_entries_serialized_array_primary_write |
|
77 |
|
#define entries_serialized_array_secondary_write nyangpt_entries_serialized_array_secondary_write |
|
78 |
|
#define entries_show nyangpt_entries_show |
|
79 |
|
#define entry_bytes_n nyangpt_entry_bytes_n |
|
80 |
|
#define entry_delete nyangpt_entry_delete |
|
81 |
|
#define entry_is_used nyangpt_entry_is_used |
|
82 |
|
#define entry_show nyangpt_entry_show |
|
83 |
|
#define entry_t nyangpt_entry_t |
|
84 |
|
#define error_pf nyangpt_error_pf |
|
85 |
|
#define first_lba_default_select nyangpt_first_lba_default_select |
|
86 |
|
#define gpt_write nyangpt_gpt_write |
|
87 |
|
#define guid_is_zero nyangpt_guid_is_zero |
|
88 |
|
#define guid_t nyangpt_guid_t |
|
89 |
|
#define guid_randomize nyangpt_guid_randomize |
|
90 |
|
#define guid_read nyangpt_guid_read |
|
91 |
|
#define guid_read_from_input nyangph_guid_read_from_input |
|
92 |
|
#define guid_write nyangpt_guid_write |
|
93 |
|
#define hdr_load nyangpt_hdr_load |
|
94 |
|
#define hdr_show nyangpt_hdr_show |
|
95 |
|
#define hdr_primary_serialized nyangpt_hdr_primary_serialized |
|
96 |
|
#define hdr_primary_serialized_gen nyangpt_hdr_primary_serialized_gen |
|
97 |
|
#define hdr_primary_serialized_write nyangpt_hdr_primary_serialized_write |
|
98 |
|
#define hdr_secondary_serialized nyangpt_hdr_secondary_serialized |
|
99 |
|
#define hdr_secondary_serialized_gen nyangpt_hdr_secondary_serialized_gen |
|
100 |
|
#define hdr_secondary_serialized_write nyangpt_hdr_secondary_serialized_write |
|
101 |
|
#define hdr_t nyangpt_hdr_t |
|
102 |
|
#define hdr_validate nyangpt_hdr_validate |
|
103 |
|
#define hdrs nyangpt_hdrs |
|
104 |
|
#define hdrs_usable_lbas_compute nyangpt_hdrs_usable_lbas_compute |
|
105 |
|
#define init_once nyangpt_init_once |
|
106 |
|
#define input_line nyangpt_input_line |
|
107 |
|
#define input_line_consume nyangpt_input_line_consume |
|
108 |
|
#define input_line_loop nyangpt_input_line_loop |
|
109 |
|
#define input_state nyangpt_input_state |
|
110 |
|
#define last_lba_default_select nyangpt_last_lba_default_select |
|
111 |
|
#define le_crc32_for_byte nyangpt_le_crc32_for_byte |
|
112 |
|
#define le_crc32_tbl nyangpt_le_crc32_tbl |
|
113 |
|
#define le_crc32_tbl_gen nyangpt_le_crc32_tbl_gen |
|
114 |
|
#define le_crc32_update nyangpt_le_crc32_update |
|
115 |
|
#define load_previous_gpt nyangpt_load_previous_gpt |
|
116 |
|
#define main_menu_prompt nyangpt_main_menu_prompt |
|
117 |
|
#define main_menu_show nyangpt_main_menu_show |
|
118 |
|
#define options_parse nyangpt_options_parse |
|
119 |
|
#define out_bold_pf nyangpt_out_bold_pf |
|
120 |
|
#define out_guid nyangpt_out_guid |
|
121 |
|
#define out_pf nyangpt_out_pf |
|
122 |
|
#define pf nyangpt_pf |
|
123 |
|
#define previous_gpt_load nyangpt_previous_gpt_load |
|
124 |
|
#define protective_mbr nyangpt_protective_mbr |
|
125 |
|
#define protective_mbr_gen nyangpt_protective_mbr_gen |
|
126 |
|
#define protective_mbr_write nyangpt_protective_mbr_write |
|
127 |
|
#define read_full nyangpt_read_full |
|
128 |
|
#define state_change_disk_guid nyangpt_state_change_disk_guid |
|
129 |
|
#define state_delete_entry nyangpt_state_delete_entry |
|
130 |
|
#define state_edit_entry nyangpt_state_edit_entry |
|
131 |
|
#define state_edit_entry_substate_attrs nyangpt_state_edit_entry_substate_attrs |
|
132 |
|
#define state_edit_entry_substate_first_lba nyangpt_state_edit_entry_substate_first_lba |
|
133 |
|
#define state_edit_entry_substate_last_lba nyangpt_state_edit_entry_substate_last_lba |
|
134 |
|
#define state_edit_entry_substate_type nyangpt_state_edit_entry_substate_type |
|
135 |
|
#define state_edit_entry_substate_uniq_quid nyangpt_state_edit_entry_substate_uniq_quid |
|
136 |
|
#define state_main_menu nyangpt_state_main_menu |
|
137 |
|
#define sysfs_infos_get nyangpt_sysfs_infos_get |
|
138 |
|
#define type_guids_lookup_name nyangpt_type_guids_lookup_name |
|
139 |
|
#define types nyangpt_types |
|
140 |
|
#define types_show nyangpt_types_show |
|
141 |
|
#define usage nyangpt_usage |
|
142 |
|
#define utf16_strdup nyangpt_utf16_strdup |
|
143 |
|
#define warning_pf nyangpt_warning_pf |
|
144 |
|
#define write_full nyangpt_write_full |
|
145 |
|
/*----------------------------------------------------------------------------*/ |
|
146 |
|
#define nyangpt_main main |
|
147 |
|
/*}}} nyangpt namespace -- end -----------------------------------------------*/ |
|
148 |
|
/*{{{ crc32b little endian */ |
|
149 |
|
/* stolen and cosmetized, not validated on big endian */ |
|
150 |
|
/* http://home.thep.lu.se/~bjorn/crc/ */ |
|
151 |
|
STATIC u32 le_crc32_for_byte(u32 r) |
|
152 |
|
{ |
|
153 |
|
u8 j; |
|
154 |
|
|
|
155 |
|
j = 0; |
|
156 |
|
loop { |
|
157 |
|
if (j == 8) |
|
158 |
|
break; |
|
159 |
|
r = (r & 1 ? 0 : (u32)0xedb88320) ^ r >> 1; |
|
160 |
|
++j; |
|
161 |
|
} |
|
162 |
|
return r ^ (u32)0xff000000; |
|
163 |
|
} |
|
164 |
|
STATIC u32 le_crc32_tbl[0x100]; |
|
165 |
|
STATIC void le_crc32_tbl_gen(void) |
|
166 |
|
{ |
|
167 |
|
u32 i; |
|
168 |
|
|
|
169 |
|
i = 0; |
|
170 |
|
loop { |
|
171 |
|
if (i == 0x100) |
|
172 |
|
break; |
|
173 |
|
le_crc32_tbl[i] = le_crc32_for_byte(i); |
|
174 |
|
++i; |
|
175 |
|
} |
|
176 |
|
} |
|
177 |
|
STATIC void le_crc32_update(void *data, u64 bytes_n, u32* crc) |
|
178 |
|
{ |
|
179 |
|
u64 i; |
|
180 |
|
|
|
181 |
|
i = 0; |
|
182 |
|
loop { |
|
183 |
|
if (i == bytes_n) |
|
184 |
|
break; |
|
185 |
|
*crc = le_crc32_tbl[(u8)*crc ^ ((u8*)data)[i]] ^ *crc >> 8; |
|
186 |
|
++i; |
|
187 |
|
} |
|
188 |
|
} |
|
189 |
|
/*}}} crc32b little endian -- end *********************************************/ |
|
190 |
|
/*{{{ types */ |
|
191 |
|
struct guid_t { |
|
192 |
|
u32 blk_0; |
|
193 |
|
u16 blk_1; |
|
194 |
|
u16 blk_2; |
|
195 |
|
u16 blk_3; |
|
196 |
|
u8 blk_4[6]; |
|
197 |
|
}; |
|
198 |
|
/* serialized offsets */ |
|
199 |
|
#define BLK_0 0x0 |
|
200 |
|
#define BLK_1 0x4 |
|
201 |
|
#define BLK_2 0x6 |
|
202 |
|
#define BLK_3 0x8 |
|
203 |
|
#define BLK_4 0xa |
|
204 |
|
/*----------------------------------------------------------------------------*/ |
|
205 |
|
struct hdr_t { |
|
206 |
|
bool valid; |
|
207 |
|
utf8 *str; |
|
208 |
|
u64 read_from_lba; /* _should_ be the same as the lba field */ |
|
209 |
|
|
|
210 |
|
u8 *data; |
|
211 |
|
/* fields -- start */ |
|
212 |
|
/* signature */ |
|
213 |
|
/* revision */ |
|
214 |
|
u32 bytes_n; |
|
215 |
|
u32 le_crc32; |
|
216 |
|
u64 lba; |
|
217 |
|
u64 alternate_hdr_lba; |
|
218 |
|
/* first usable lba */ |
|
219 |
|
/* last usable lba */ |
|
220 |
|
struct guid_t disk_guid; |
|
221 |
|
u64 entries_lba; |
|
222 |
|
u32 entries_n; |
|
223 |
|
u32 entry_bytes_n; |
|
224 |
|
u32 entries_le_crc32; |
|
225 |
|
/* fields -- end */ |
|
226 |
|
|
|
227 |
|
bool entries_valid; |
|
228 |
|
u8 *entries; |
|
229 |
|
}; |
|
230 |
|
/*----------------------------------------------------------------------------*/ |
|
231 |
|
struct entry_t { |
|
232 |
|
struct guid_t type; |
|
233 |
|
struct guid_t uniq; |
|
234 |
|
u64 first; |
|
235 |
|
u64 last; |
|
236 |
|
u64 attrs; |
|
237 |
|
utf16 *name; |
|
238 |
|
}; |
|
239 |
|
#define ENTRIES_ARRAY_MIN_BYTES_N 16384 /* specs: minimum to book on the disk */ |
|
240 |
|
#define ENTRY_BYTES_N 0x80 /* specs */ |
|
241 |
|
/*}}} types -- end */ |
|
242 |
|
STATIC bool colors_on; |
|
243 |
|
STATIC bool load_previous_gpt; |
|
244 |
|
/*----------------------------------------------------------------------------*/ |
|
245 |
|
STATIC struct { |
|
246 |
|
utf8 *path; |
|
247 |
|
u64 sz_512_n; |
|
248 |
|
u64 logical_blk_bytes_n; |
|
249 |
|
u64 physical_blk_bytes_n; |
|
250 |
|
int fd; |
|
251 |
|
u64 last_lba; |
|
252 |
|
} blk_dev; |
|
253 |
|
/*----------------------------------------------------------------------------*/ |
|
254 |
|
STATIC u8 *protective_mbr; |
|
255 |
|
/* serialized offsets */ |
|
256 |
|
#define BOOT_SIGNATURE_0X55 0x1fe |
|
257 |
|
#define BOOT_SIGNATURE_0XAA 0x1ff |
|
258 |
|
#define PART_0 0x1be |
|
259 |
|
/*----------------------------------------------------------------------------*/ |
|
260 |
|
STATIC struct { /* there are 2 headers, each must fit in a logical block */ |
|
261 |
|
u64 first_usable_lba; |
|
262 |
|
u64 last_usable_lba; |
|
263 |
|
struct guid_t disk_guid; |
|
264 |
|
u32 bytes_n; /* the mitigated hdr size */ |
|
265 |
|
|
|
266 |
|
struct { |
|
267 |
|
struct hdr_t primary; |
|
268 |
|
struct hdr_t secondary; |
|
269 |
|
} previous; |
|
270 |
|
} hdrs; |
|
271 |
|
#define HDR_SIGNATURE "EFI PART" |
|
272 |
|
#define HDR_SIGNATURE_BYTES_N 8 |
|
273 |
|
#define HDR_REVISION 0x00010000 /* 1.0 */ |
|
274 |
|
#define HDR_BYTES_N 0x5c /* specs: 92 bytes */ |
|
275 |
|
STATIC u8 *hdr_primary_serialized; |
|
276 |
|
STATIC u8 *hdr_secondary_serialized; |
|
277 |
|
/*----------------------------------------------------------------------------*/ |
|
278 |
|
STATIC struct entry_t *entries; |
|
279 |
|
STATIC u32 entries_n; |
|
280 |
|
STATIC u32 entry_bytes_n; |
|
281 |
|
STATIC u32 entries_lbas_n; |
|
282 |
|
STATIC u8 *entries_serialized_array; |
|
283 |
|
STATIC u32 entries_serialized_array_crc32; |
|
284 |
|
/*----------------------------------------------------------------------------*/ |
|
285 |
|
STATIC utf8 *pf(utf8 *fmt,...) |
|
286 |
|
{ |
|
287 |
|
va_list ap; |
|
288 |
|
int r; |
|
289 |
|
utf8 *r_str; |
|
290 |
|
|
|
291 |
|
va_start(ap, fmt); |
|
292 |
|
r = vsnprintf(0, 0, fmt, ap); |
|
293 |
|
va_end(ap); |
|
294 |
|
|
|
295 |
|
r_str = malloc(r + 1); /* we want a terminating 0 */ |
|
296 |
|
|
|
297 |
|
va_start(ap, fmt); |
|
298 |
|
vsnprintf(r_str, r + 1, fmt, ap); /* has room for the terminating 0 */ |
|
299 |
|
va_end(ap); |
|
300 |
|
return r_str; |
|
301 |
|
} |
|
302 |
|
#define BOLD_RED if (colors_on) dprintf(1,"\x1b[38;2;255;0;0m\x1b[1m") |
|
303 |
|
#define BOLD_ORANGE if (colors_on) dprintf(1,"\x1b[38;2;255;140;0m\x1b[1m") |
|
304 |
|
#define BOLD if (colors_on) dprintf(1,"\x1b[1m"); |
|
305 |
|
#define RESTORE if (colors_on) dprintf(1, "\x1b[m") |
|
306 |
|
STATIC void error_pf(utf8 *fmt,...) |
|
307 |
|
{ |
|
308 |
|
va_list ap; |
|
309 |
|
|
|
310 |
|
BOLD_RED; |
|
311 |
|
dprintf(1, "ERROR:"); |
|
312 |
|
va_start(ap, fmt); |
|
313 |
|
vdprintf(1, fmt, ap); |
|
314 |
|
va_end(ap); |
|
315 |
|
RESTORE; |
|
316 |
|
exit(1); |
|
317 |
|
} |
|
318 |
|
STATIC void warning_pf(utf8 *fmt,...) |
|
319 |
|
{ |
|
320 |
|
va_list ap; |
|
321 |
|
|
|
322 |
|
BOLD_ORANGE; |
|
323 |
|
dprintf(1, "WARNING:"); |
|
324 |
|
va_start(ap, fmt); |
|
325 |
|
vdprintf(1, fmt, ap); |
|
326 |
|
va_end(ap); |
|
327 |
|
RESTORE; |
|
328 |
|
} |
|
329 |
|
STATIC void out_pf(utf8 *fmt,...) |
|
330 |
|
{ |
|
331 |
|
va_list ap; |
|
332 |
|
|
|
333 |
|
va_start(ap, fmt); |
|
334 |
|
vdprintf(1, fmt, ap); |
|
335 |
|
va_end(ap); |
|
336 |
|
} |
|
337 |
|
STATIC void out_bold_pf(utf8 *fmt,...) |
|
338 |
|
{ |
|
339 |
|
va_list ap; |
|
340 |
|
|
|
341 |
|
BOLD; |
|
342 |
|
va_start(ap, fmt); |
|
343 |
|
vdprintf(1, fmt, ap); |
|
344 |
|
va_end(ap); |
|
345 |
|
RESTORE; |
|
346 |
|
} |
|
347 |
|
STATIC bool read_full(int fd, void *dest, u64 bytes_n) |
|
348 |
|
{ |
|
349 |
|
u64 read_bytes_n; |
|
350 |
|
|
|
351 |
|
read_bytes_n = 0; |
|
352 |
|
loop { |
|
353 |
|
ssize_t r; |
|
354 |
|
|
|
355 |
|
errno = 0; |
|
356 |
|
r = read(fd, dest + read_bytes_n, |
|
357 |
|
(size_t)(bytes_n - read_bytes_n)); |
|
358 |
|
if (r == -1) { |
|
359 |
|
if (errno == EINTR) |
|
360 |
|
continue; |
|
361 |
|
return false; |
|
362 |
|
} |
|
363 |
|
read_bytes_n += (u64)r; |
|
364 |
|
if (read_bytes_n == bytes_n) |
|
365 |
|
return true; |
|
366 |
|
} |
|
367 |
|
/* unreachable */ |
|
368 |
|
} |
|
369 |
|
STATIC bool write_full(int fd, void *src, u64 bytes_n) |
|
370 |
|
{ |
|
371 |
|
u64 written_bytes_n; |
|
372 |
|
|
|
373 |
|
/* short writes */ |
|
374 |
|
written_bytes_n = 0; |
|
375 |
|
loop { |
|
376 |
|
ssize_t r; |
|
377 |
|
|
|
378 |
|
errno = 0; |
|
379 |
|
r = write(blk_dev.fd, src + written_bytes_n, |
|
380 |
|
(size_t)(bytes_n - written_bytes_n)); |
|
381 |
|
if (r == -1) { |
|
382 |
|
if (errno == EINTR) |
|
383 |
|
continue; |
|
384 |
|
return false; |
|
385 |
|
} |
|
386 |
|
written_bytes_n += (u64)r; |
|
387 |
|
if (written_bytes_n == bytes_n) |
|
388 |
|
return true; |
|
389 |
|
} |
|
390 |
|
/* unreachable */ |
|
391 |
|
} |
|
392 |
|
STATIC utf16 *utf16_strdup(utf16 *start) |
|
393 |
|
{ |
|
394 |
|
utf16 *end; |
|
395 |
|
utf16 *dst; |
|
396 |
|
size_t bytes_n; |
|
397 |
|
|
|
398 |
|
end = start; |
|
399 |
|
loop { |
|
400 |
|
if (*end == 0) |
|
401 |
|
break; |
|
402 |
|
++end; |
|
403 |
|
} |
|
404 |
|
++end; |
|
405 |
|
bytes_n = (size_t)((end - start) * sizeof(utf16)); |
|
406 |
|
dst = calloc(1,bytes_n); |
|
407 |
|
memcpy(dst, start, bytes_n); |
|
408 |
|
} |
|
409 |
|
/* brain damaged mixed-endian guid */ |
|
410 |
|
STATIC void guid_write(void *dest, struct guid_t *src) |
|
411 |
|
{ |
|
412 |
|
u8 *d; |
|
413 |
|
u32 *p32; |
|
414 |
|
u16 *p16; |
|
415 |
|
|
|
416 |
|
d = (u8*)dest; |
|
417 |
|
|
|
418 |
|
p32 = (u32*)d; |
|
419 |
|
*p32 = htole32(src->blk_0); /* little endian */ |
|
420 |
|
d += 4; |
|
421 |
|
p16 = (u16*)d; |
|
422 |
|
*p16 = htole16(src->blk_1); /* little endian */ |
|
423 |
|
d += 2; |
|
424 |
|
p16 = (u16*)d; |
|
425 |
|
*p16 = htole16(src->blk_2); /* little endian */ |
|
426 |
|
d += 2; |
|
427 |
|
p16 = (u16*)d; |
|
428 |
|
*p16 = htobe16(src->blk_3); /* big endian */ |
|
429 |
|
d += 2; |
|
430 |
|
d[0] = src->blk_4[0]; |
|
431 |
|
d[1] = src->blk_4[1]; |
|
432 |
|
d[2] = src->blk_4[2]; |
|
433 |
|
d[3] = src->blk_4[3]; |
|
434 |
|
d[4] = src->blk_4[4]; |
|
435 |
|
d[5] = src->blk_4[5]; |
|
436 |
|
} |
|
437 |
|
/* brain damaged mixed-endian guid */ |
|
438 |
|
STATIC void guid_read(struct guid_t *dest, void *src) |
|
439 |
|
{ |
|
440 |
|
u32 *p32; |
|
441 |
|
u16 *p16; |
|
442 |
|
u8 *p8; |
|
443 |
|
|
|
444 |
|
p32 = src; |
|
445 |
|
dest->blk_0 = le32toh(*p32); |
|
446 |
|
src += 4; |
|
447 |
|
p16 = src; |
|
448 |
|
dest->blk_1 = le16toh(*p16); |
|
449 |
|
src += 2; |
|
450 |
|
p16 = src; |
|
451 |
|
dest->blk_2 = le16toh(*p16); |
|
452 |
|
src += 2; |
|
453 |
|
p16 = src; |
|
454 |
|
dest->blk_3 = be16toh(*p16); |
|
455 |
|
src += 2; |
|
456 |
|
memcpy(dest->blk_4, src, 6); |
|
457 |
|
} |
|
458 |
|
STATIC void sysfs_infos_get(void) |
|
459 |
|
{ |
|
460 |
|
int fd; |
|
461 |
|
int r; |
|
462 |
|
utf8 val_str[X64_UTF8_BYTES_MAX + 1]; /* 0 terminating char */ |
|
463 |
|
utf8 *blk_dev_name; |
|
464 |
|
utf8 *sz_512_n_path; |
|
465 |
|
utf8 *logical_blk_bytes_n_path; |
|
466 |
|
utf8 *physical_blk_bytes_n_path; |
|
467 |
|
|
|
468 |
|
blk_dev_name = strrchr(blk_dev.path, '/'); |
|
469 |
|
++blk_dev_name; |
|
470 |
|
sz_512_n_path = pf("/sys/block/%s/size", blk_dev_name); |
|
471 |
|
out_pf("%s:reading %s\n", blk_dev.path, sz_512_n_path); |
|
472 |
|
fd = open(sz_512_n_path, O_RDONLY); |
|
473 |
|
if (fd == -1) |
|
474 |
|
error_pf("%s:unable to open %s\n", blk_dev.path, sz_512_n_path); |
|
475 |
|
free(sz_512_n_path); |
|
476 |
|
/* reads are supposed to be atomic from sysfs... I guess */ |
|
477 |
|
r = read(fd, val_str, sizeof(val_str)); |
|
478 |
|
val_str[r - 1] = 0; /* remove the terminating '\n' */ |
|
479 |
|
blk_dev.sz_512_n = strtou64(val_str, 0, 10); |
|
480 |
|
out_bold_pf("%s:size is %"PRIu64" blocks of 512 bytes\n", blk_dev.path, blk_dev.sz_512_n); |
|
481 |
|
close(fd); |
|
482 |
|
|
|
483 |
|
logical_blk_bytes_n_path = pf("/sys/block/%s/queue/logical_block_size", blk_dev_name); |
|
484 |
|
out_pf("%s:reading %s\n", blk_dev.path, logical_blk_bytes_n_path); |
|
485 |
|
fd = open(logical_blk_bytes_n_path, O_RDONLY); |
|
486 |
|
if (fd == -1) |
|
487 |
|
error_pf("%s:unable to open %s\n", blk_dev.path, logical_blk_bytes_n_path); |
|
488 |
|
free(logical_blk_bytes_n_path); |
|
489 |
|
/* reads are supposed to be atomic from sysfs... I guess */ |
|
490 |
|
r = read(fd, val_str, sizeof(val_str)); |
|
491 |
|
val_str[r - 1] = 0; /* remove the terminating '\n' */ |
|
492 |
|
blk_dev.logical_blk_bytes_n = strtou64(val_str, 0, 10); |
|
493 |
|
out_bold_pf("%s:logical block size is %"PRIu64" bytes\n", blk_dev.path, blk_dev.logical_blk_bytes_n); |
|
494 |
|
close(fd); |
|
495 |
|
|
|
496 |
|
physical_blk_bytes_n_path = pf("/sys/block/%s/queue/physical_block_size", blk_dev_name); |
|
497 |
|
out_pf("%s:reading %s\n", blk_dev.path, physical_blk_bytes_n_path); |
|
498 |
|
fd = open(physical_blk_bytes_n_path, O_RDONLY); |
|
499 |
|
if (fd == -1) |
|
500 |
|
error_pf("%s:unable to open %s\n", blk_dev.path, physical_blk_bytes_n_path); |
|
501 |
|
free(physical_blk_bytes_n_path); |
|
502 |
|
/* reads are supposed to be atomic from sysfs... I guess */ |
|
503 |
|
r = read(fd, val_str, sizeof(val_str)); |
|
504 |
|
val_str[r - 1] = 0; /* remove the terminating '\n' */ |
|
505 |
|
blk_dev.physical_blk_bytes_n = strtou64(val_str, 0, 10); |
|
506 |
|
out_bold_pf("%s:physical block size is %"PRIu64" bytes\n", blk_dev.path, blk_dev.physical_blk_bytes_n); |
|
507 |
|
close(fd); |
|
508 |
|
} |
|
509 |
|
STATIC void protective_mbr_gen(void) |
|
510 |
|
{ |
|
511 |
|
u32 *le32_whole_dev_logical_blks_n; |
|
512 |
|
u64 whole_dev_bytes_n; |
|
513 |
|
u64 whole_dev_logical_blks_n; |
|
514 |
|
|
|
515 |
|
if (blk_dev.logical_blk_bytes_n < 512) |
|
516 |
|
error_pf("%s: something is wrong, the logical block size is %"PRIu64", below 512/0x200 bytes", blk_dev.path, blk_dev.logical_blk_bytes_n); |
|
517 |
|
protective_mbr = calloc(1, blk_dev.logical_blk_bytes_n); |
|
518 |
|
|
|
519 |
|
protective_mbr[PART_0 + 0x02] = 0x02; /* first CHS */ |
|
520 |
|
protective_mbr[PART_0 + 0x04] = 0xee; /* partition type */ |
|
521 |
|
protective_mbr[PART_0 + 0x05] = 0xff; /* last head */ |
|
522 |
|
protective_mbr[PART_0 + 0x06] = 0xff; /* last cylinder MSBs + last sector */ |
|
523 |
|
protective_mbr[PART_0 + 0x07] = 0xff; /* last cylinder LSBs */ |
|
524 |
|
protective_mbr[PART_0 + 0x08] = 0x1; /* little endian */ |
|
525 |
|
|
|
526 |
|
whole_dev_bytes_n = blk_dev.sz_512_n * 512; |
|
527 |
|
whole_dev_logical_blks_n = whole_dev_bytes_n / blk_dev.logical_blk_bytes_n; |
|
528 |
|
/* cap to max, remove the MBR in LBA 0 */ |
|
529 |
|
if (whole_dev_logical_blks_n > 0x100000000) |
|
530 |
|
whole_dev_logical_blks_n = 0xffffffff; |
|
531 |
|
le32_whole_dev_logical_blks_n = (u32*)&protective_mbr[PART_0 + 0x0c]; |
|
532 |
|
*le32_whole_dev_logical_blks_n = htole32( /* remove mbr */ |
|
533 |
|
(u32)whole_dev_logical_blks_n - 1); |
|
534 |
|
|
|
535 |
|
protective_mbr[BOOT_SIGNATURE_0X55] = 0x55; |
|
536 |
|
protective_mbr[BOOT_SIGNATURE_0XAA] = 0xaa; |
|
537 |
|
} |
|
538 |
|
STATIC void protective_mbr_write(void) |
|
539 |
|
{ |
|
540 |
|
off_t r0; |
|
541 |
|
|
|
542 |
|
r0 = lseek(blk_dev.fd, 0, SEEK_SET); |
|
543 |
|
if (r0 != 0) |
|
544 |
|
error_pf("%s:unable to reach the start of the device\n", blk_dev.path); |
|
545 |
|
if (!write_full(blk_dev.fd, protective_mbr, |
|
546 |
|
blk_dev.logical_blk_bytes_n)) |
|
547 |
|
error_pf("%s:unable to write the protective master boot record (mbr), device mbr is now probably corrupted\n", blk_dev.path); |
|
548 |
|
out_bold_pf("%s:protective master boot record (mbr) written, %"PRIu64" bytes\n", blk_dev.path, blk_dev.logical_blk_bytes_n); |
|
549 |
|
} |
|
550 |
|
STATIC void entries_serialized_array_gen_entry(u32 entry_idx) |
|
551 |
|
{ |
|
552 |
|
u8 *entry; |
|
553 |
|
u64 *p64; |
|
554 |
|
|
|
555 |
|
entry = entries_serialized_array + entry_bytes_n * entry_idx; |
|
556 |
|
guid_write(&entry[0x00], &entries[entry_idx].type); |
|
557 |
|
guid_write(&entry[0x10], &entries[entry_idx].uniq); |
|
558 |
|
p64 = (u64*)&entry[0x20]; |
|
559 |
|
*p64 = htole64(entries[entry_idx].first); |
|
560 |
|
p64 = (u64*)&entry[0x28]; |
|
561 |
|
*p64 = htole64(entries[entry_idx].last); |
|
562 |
|
} |
|
563 |
|
STATIC void entries_serialized_array_gen(void) |
|
564 |
|
{ |
|
565 |
|
u32 entry_idx; |
|
566 |
|
|
|
567 |
|
entries_serialized_array = calloc(1, entries_lbas_n |
|
568 |
|
* blk_dev.logical_blk_bytes_n); |
|
569 |
|
entry_idx = 0; |
|
570 |
|
loop { |
|
571 |
|
if (entry_idx == entries_n) |
|
572 |
|
break; |
|
573 |
|
entries_serialized_array_gen_entry(entry_idx); |
|
574 |
|
++entry_idx; |
|
575 |
|
} |
|
576 |
|
} |
|
577 |
|
STATIC void hdr_primary_serialized_gen(void) |
|
578 |
|
{ |
|
579 |
|
u64 *p64; |
|
580 |
|
u32 *p32; |
|
581 |
|
u16 *p16; |
|
582 |
|
u32 le_crc32; |
|
583 |
|
|
|
584 |
|
hdr_primary_serialized = calloc(1, blk_dev.logical_blk_bytes_n); |
|
585 |
|
|
|
586 |
|
memcpy(hdr_primary_serialized, HDR_SIGNATURE, 8); |
|
587 |
|
|
|
588 |
|
p32 = (u32*)&hdr_primary_serialized[0x08]; |
|
589 |
|
*p32 = htole32(HDR_REVISION); |
|
590 |
|
|
|
591 |
|
p32 =(u32*)&hdr_primary_serialized[0x0c]; |
|
592 |
|
*p32 = htole32(hdrs.bytes_n); |
|
593 |
|
|
|
594 |
|
/* the CRC32 will go there, 0 for its calculation */ |
|
595 |
|
|
|
596 |
|
p64 = (u64*)&hdr_primary_serialized[0x18]; |
|
597 |
|
*p64 = htole64(0x00000001); /* lba of this hdr */ |
|
598 |
|
|
|
599 |
|
p64 = (u64*)&hdr_primary_serialized[0x20]; |
|
600 |
|
*p64 = htole64(blk_dev.last_lba); /* the hdr at the end */ |
|
601 |
|
|
|
602 |
|
p64 = (u64*)&hdr_primary_serialized[0x28]; |
|
603 |
|
*p64 = htole64(hdrs.first_usable_lba); |
|
604 |
|
|
|
605 |
|
p64 = (u64*)&hdr_primary_serialized[0x30]; |
|
606 |
|
*p64 = htole64(hdrs.last_usable_lba); |
|
607 |
|
|
|
608 |
|
guid_write(&hdr_primary_serialized[0x38], &hdrs.disk_guid); |
|
609 |
|
|
|
610 |
|
p64 = (u64*)&hdr_primary_serialized[0x48]; |
|
611 |
|
*p64 = htole64(2); /* skip mbr and hdr */ |
|
612 |
|
|
|
613 |
|
p32 = (u32*)&hdr_primary_serialized[0x50]; |
|
614 |
|
*p32 = htole32(entries_n); |
|
615 |
|
|
|
616 |
|
p32 = (u32*)&hdr_primary_serialized[0x54]; |
|
617 |
|
*p32 = htole32(entry_bytes_n); |
|
618 |
|
|
|
619 |
|
p32 = (u32*)&hdr_primary_serialized[0x58]; |
|
620 |
|
*p32 = htole32(entries_serialized_array_crc32); |
|
621 |
|
|
|
622 |
|
/* crc32 on exactly the header size */ |
|
623 |
|
le_crc32 = 0; |
|
624 |
|
le_crc32_update(hdr_primary_serialized, hdrs.bytes_n, &le_crc32); |
|
625 |
|
p32 = (u32*)&hdr_primary_serialized[0x10]; |
|
626 |
|
*p32 = le_crc32; |
|
627 |
|
} |
|
628 |
|
STATIC void hdr_secondary_serialized_gen(void) |
|
629 |
|
{ |
|
630 |
|
u64 *p64; |
|
631 |
|
u32 *p32; |
|
632 |
|
u16 *p16; |
|
633 |
|
u32 le_crc32; |
|
634 |
|
|
|
635 |
|
hdr_secondary_serialized = calloc(1, blk_dev.logical_blk_bytes_n); |
|
636 |
|
|
|
637 |
|
memcpy(hdr_secondary_serialized, HDR_SIGNATURE, 8); |
|
638 |
|
|
|
639 |
|
p32 = (u32*)&hdr_secondary_serialized[0x08]; |
|
640 |
|
*p32 = htole32(HDR_REVISION); |
|
641 |
|
|
|
642 |
|
p32 =(u32*)&hdr_secondary_serialized[0x0c]; |
|
643 |
|
*p32 = htole32(hdrs.bytes_n); |
|
644 |
|
|
|
645 |
|
/* the CRC32 will go there, 0 for its calculation */ |
|
646 |
|
|
|
647 |
|
p64 = (u64*)&hdr_secondary_serialized[0x18]; |
|
648 |
|
*p64 = htole64(blk_dev.last_lba); /* this hdr */ |
|
649 |
|
|
|
650 |
|
p64 = (u64*)&hdr_secondary_serialized[0x20]; |
|
651 |
|
*p64 = htole64(1); /* the hdr at the beginning */ |
|
652 |
|
|
|
653 |
|
p64 = (u64*)&hdr_secondary_serialized[0x28]; |
|
654 |
|
*p64 = htole64(hdrs.first_usable_lba); |
|
655 |
|
|
|
656 |
|
p64 = (u64*)&hdr_secondary_serialized[0x30]; |
|
657 |
|
*p64 = htole64(hdrs.last_usable_lba); |
|
658 |
|
|
|
659 |
|
guid_write(&hdr_secondary_serialized[0x38], &hdrs.disk_guid); |
|
660 |
|
|
|
661 |
|
p64 = (u64*)&hdr_secondary_serialized[0x48]; |
|
662 |
|
*p64 = htole64(blk_dev.last_lba - entries_lbas_n); |
|
663 |
|
|
|
664 |
|
p32 = (u32*)&hdr_secondary_serialized[0x50]; |
|
665 |
|
*p32 = htole32(entries_n); |
|
666 |
|
|
|
667 |
|
p32 = (u32*)&hdr_secondary_serialized[0x54]; |
|
668 |
|
*p32 = htole32(entry_bytes_n); |
|
669 |
|
|
|
670 |
|
p32 = (u32*)&hdr_secondary_serialized[0x58]; |
|
671 |
|
*p32 = htole32(entries_serialized_array_crc32); |
|
672 |
|
|
|
673 |
|
/* crc32 on exactly the header size */ |
|
674 |
|
le_crc32 = 0; |
|
675 |
|
le_crc32_update(hdr_secondary_serialized, hdrs.bytes_n, &le_crc32); |
|
676 |
|
p32 = (u32*)&hdr_secondary_serialized[0x10]; |
|
677 |
|
*p32 = le_crc32; |
|
678 |
|
} |
|
679 |
|
STATIC void hdr_primary_serialized_write(void) |
|
680 |
|
{ |
|
681 |
|
off_t r; |
|
682 |
|
off_t start; |
|
683 |
|
u64 bytes_to_write_n; |
|
684 |
|
|
|
685 |
|
/* skip the mbr */ |
|
686 |
|
start = (off_t)blk_dev.logical_blk_bytes_n; |
|
687 |
|
r = lseek(blk_dev.fd, start, SEEK_SET); |
|
688 |
|
if (r != start) |
|
689 |
|
error_pf("%s:unable to reach the first lba of the device\n", blk_dev.path); |
|
690 |
|
bytes_to_write_n = (size_t)(blk_dev.logical_blk_bytes_n); |
|
691 |
|
if (!write_full(blk_dev.fd, hdr_primary_serialized, bytes_to_write_n)) |
|
692 |
|
error_pf("%s:unable to write the primary GPT header, block device is now probably corrupted\n", blk_dev.path); |
|
693 |
|
out_bold_pf("%s:primary GPT header written, %"PRIu64" bytes\n", blk_dev.path, bytes_to_write_n); |
|
694 |
|
} |
|
695 |
|
STATIC void hdr_secondary_serialized_write(void) |
|
696 |
|
{ |
|
697 |
|
off_t r; |
|
698 |
|
off_t start; |
|
699 |
|
u64 bytes_to_write_n; |
|
700 |
|
|
|
701 |
|
start = (off_t)(blk_dev.last_lba * blk_dev.logical_blk_bytes_n); |
|
702 |
|
r = lseek(blk_dev.fd, start, SEEK_SET); |
|
703 |
|
if (r != start) |
|
704 |
|
error_pf("%s:unable to reach the lba of the secondary header\n", blk_dev.path); |
|
705 |
|
bytes_to_write_n = blk_dev.logical_blk_bytes_n; |
|
706 |
|
if (!write_full(blk_dev.fd, hdr_secondary_serialized, bytes_to_write_n)) |
|
707 |
|
error_pf("%s:unable to write the secondary GPT header, block device is now probably corrupted\n", blk_dev.path); |
|
708 |
|
out_bold_pf("%s:secondary GPT header written, %"PRIu64" bytes\n", blk_dev.path, bytes_to_write_n); |
|
709 |
|
} |
|
710 |
|
STATIC void entries_serialized_array_primary_write(void) |
|
711 |
|
{ |
|
712 |
|
off_t r; |
|
713 |
|
off_t start; |
|
714 |
|
u64 bytes_to_write_n; |
|
715 |
|
|
|
716 |
|
/* skip the mbr and the primary hdr */ |
|
717 |
|
start = (off_t)(blk_dev.logical_blk_bytes_n * 2); |
|
718 |
|
r = lseek(blk_dev.fd, start, SEEK_SET); |
|
719 |
|
if (r != start) |
|
720 |
|
error_pf("%s:unable to reach the first lba for the primary entries\n", blk_dev.path); |
|
721 |
|
bytes_to_write_n = blk_dev.logical_blk_bytes_n * entries_lbas_n; |
|
722 |
|
if (!write_full(blk_dev.fd, entries_serialized_array, bytes_to_write_n)) |
|
723 |
|
error_pf("%s:unable to write the primary entries, block device is now probably corrupted\n", blk_dev.path); |
|
724 |
|
out_bold_pf("%s:primary entries written, %"PRIu64" bytes\n", blk_dev.path, bytes_to_write_n); |
|
725 |
|
} |
|
726 |
|
STATIC void entries_serialized_array_secondary_write(void) |
|
727 |
|
{ |
|
728 |
|
off_t r; |
|
729 |
|
off_t start; |
|
730 |
|
u64 bytes_to_write_n; |
|
731 |
|
|
|
732 |
|
/* skip the secondary hdr, offset arithmetic */ |
|
733 |
|
start = (off_t)(blk_dev.logical_blk_bytes_n * (blk_dev.last_lba |
|
734 |
|
- entries_lbas_n)); |
|
735 |
|
r = lseek(blk_dev.fd, start, SEEK_SET); |
|
736 |
|
if (r != start) |
|
737 |
|
error_pf("%s:unable to reach the first lba for the secondary entries\n", blk_dev.path); |
|
738 |
|
bytes_to_write_n = blk_dev.logical_blk_bytes_n * entries_lbas_n; |
|
739 |
|
if (!write_full(blk_dev.fd, entries_serialized_array, bytes_to_write_n)) |
|
740 |
|
error_pf("%s:unable to write the secondary entries, block device is now probably corrupted\n", blk_dev.path); |
|
741 |
|
out_bold_pf("%s:secondary entries written, %"PRIu64" bytes\n", blk_dev.path, bytes_to_write_n); |
|
742 |
|
} |
|
743 |
|
STATIC void hdr_load(struct hdr_t *hdr) |
|
744 |
|
{ |
|
745 |
|
off_t r; |
|
746 |
|
off_t lba_off; |
|
747 |
|
|
|
748 |
|
lba_off = (off_t)(blk_dev.logical_blk_bytes_n * hdr->read_from_lba); |
|
749 |
|
|
|
750 |
|
hdr->data = calloc(1, blk_dev.logical_blk_bytes_n); |
|
751 |
|
r = lseek(blk_dev.fd, lba_off, SEEK_SET); |
|
752 |
|
if (r != lba_off) { |
|
753 |
|
warning_pf("%s:unable to seek the device to the %s GPT header\n", blk_dev.path, hdr->str); |
|
754 |
|
return; |
|
755 |
|
} |
|
756 |
|
if (!read_full(blk_dev.fd, hdr->data, blk_dev.logical_blk_bytes_n)) { |
|
757 |
|
warning_pf("%s:unable to load the %s GPT header logical block\n", blk_dev.path, hdr->str); |
|
758 |
|
free(hdr->data); |
|
759 |
|
hdr->data = 0; |
|
760 |
|
} |
|
761 |
|
} |
|
762 |
|
STATIC void hdr_validate(struct hdr_t *hdr) |
|
763 |
|
{ |
|
764 |
|
u32 *p32; |
|
765 |
|
u32 le_crc32; |
|
766 |
|
u64 *p64; |
|
767 |
|
|
|
768 |
|
if (hdr->data == 0) |
|
769 |
|
return; |
|
770 |
|
if (memcmp(hdr->data, HDR_SIGNATURE, HDR_SIGNATURE_BYTES_N) != 0) { |
|
771 |
|
warning_pf("%s:the %s GPT header has the wrong signature\n", blk_dev.path, hdr->str); |
|
772 |
|
goto free_data; |
|
773 |
|
} |
|
774 |
|
out_bold_pf("%s:found, %s, GPT header\n", blk_dev.path, hdr->str); |
|
775 |
|
p32 = (u32*)&hdr->data[0x10]; |
|
776 |
|
hdr->le_crc32 = *p32; |
|
777 |
|
/* must 0 the crc32 to perform our crc32 */ |
|
778 |
|
*p32 = 0; |
|
779 |
|
p32 = (u32*)&hdr->data[0x0c]; |
|
780 |
|
hdr->bytes_n = le32toh(*p32); |
|
781 |
|
le_crc32 = 0; |
|
782 |
|
le_crc32_update(hdr->data, hdr->bytes_n, &le_crc32); |
|
783 |
|
if (le_crc32 != hdr->le_crc32) { |
|
784 |
|
warning_pf("%s:the %s GPT header has a bad crc32\n", blk_dev.path, hdr->str); |
|
785 |
|
goto free_data; |
|
786 |
|
} |
|
787 |
|
p64 = (u64*)&hdr->data[0x18]; |
|
788 |
|
hdr->lba = le64toh(*p64); |
|
789 |
|
p64 = (u64*)&hdr->data[0x20]; |
|
790 |
|
hdr->alternate_hdr_lba = le64toh(*p64); |
|
791 |
|
guid_read(&hdr->disk_guid, &hdr->data[0x38]); |
|
792 |
|
p64 = (u64*)&hdr->data[0x48]; |
|
793 |
|
hdr->entries_lba = le64toh(*p64); |
|
794 |
|
p32 = (u32*)&hdr->data[0x50]; |
|
795 |
|
hdr->entries_n = le32toh(*p32); |
|
796 |
|
p32 = (u32*)&hdr->data[0x54]; |
|
797 |
|
hdr->entry_bytes_n = le32toh(*p32); |
|
798 |
|
p32 = (u32*)&hdr->data[0x58]; |
|
799 |
|
hdr->entries_le_crc32 = *p32; |
|
800 |
|
|
|
801 |
|
hdr->valid = true; |
|
802 |
|
return; |
|
803 |
|
free_data: |
|
804 |
|
free(hdr->data); |
|
805 |
|
hdr->data = 0; |
|
806 |
|
} |
|
807 |
|
STATIC void entries_load(struct hdr_t *hdr) |
|
808 |
|
{ |
|
809 |
|
off_t r; |
|
810 |
|
off_t entries_off; |
|
811 |
|
u32 hdr_entries_bytes_n; |
|
812 |
|
u32 le_crc32; |
|
813 |
|
|
|
814 |
|
entries_off = hdr->entries_lba * blk_dev.logical_blk_bytes_n; |
|
815 |
|
r = lseek(blk_dev.fd, entries_off, SEEK_SET); |
|
816 |
|
if (r != entries_off) { |
|
817 |
|
warning_pf("%s:unable to seek the device to the, %s, GPT header\n", blk_dev.path, hdr->str); |
|
818 |
|
return; |
|
819 |
|
} |
|
820 |
|
hdr_entries_bytes_n = hdr->entry_bytes_n * hdr->entries_n; |
|
821 |
|
hdr->entries = calloc(1, (size_t)(hdr_entries_bytes_n)); |
|
822 |
|
if(!read_full(blk_dev.fd, hdr->entries, hdr_entries_bytes_n)) { |
|
823 |
|
warning_pf("%s:unable to read the, %s, entries\n", blk_dev.path, hdr->str); |
|
824 |
|
goto free_entries; |
|
825 |
|
} |
|
826 |
|
le_crc32 = 0; |
|
827 |
|
le_crc32_update(hdr->entries, hdr_entries_bytes_n, &le_crc32); |
|
828 |
|
if (le_crc32 != hdr->entries_le_crc32) { |
|
829 |
|
warning_pf("%s:%s entries have a bad crc32\n", blk_dev.path, hdr->str); |
|
830 |
|
goto free_entries; |
|
831 |
|
} |
|
832 |
|
hdr->entries_valid = true; |
|
833 |
|
return; |
|
834 |
|
free_entries: |
|
835 |
|
free(hdr->entries); |
|
836 |
|
} |
|
837 |
|
STATIC void build_data_from_previous_gpt(void) |
|
838 |
|
{ |
|
839 |
|
struct hdr_t *hdr; |
|
840 |
|
u32 entry_idx; |
|
841 |
|
u32 entries_bytes_n; |
|
842 |
|
|
|
843 |
|
/* first, lookup for valid data */ |
|
844 |
|
if (hdrs.previous.primary.valid && hdrs.previous.primary.entries_valid) |
|
845 |
|
hdr = &hdrs.previous.primary; |
|
846 |
|
else if (hdrs.previous.secondary.valid |
|
847 |
|
&& hdrs.previous.secondary.entries_valid) |
|
848 |
|
hdr = &hdrs.previous.secondary; |
|
849 |
|
else |
|
850 |
|
return; /* no valid data to build from */ |
|
851 |
|
/* header */ |
|
852 |
|
memcpy(&hdrs.disk_guid, &hdr->disk_guid, sizeof(hdrs.disk_guid)); |
|
853 |
|
hdrs.bytes_n = hdr->bytes_n; |
|
854 |
|
/* entries */ |
|
855 |
|
entries = calloc(hdr->entries_n, hdr->entry_bytes_n); |
|
856 |
|
entries_n = hdr->entries_n; |
|
857 |
|
entry_bytes_n = hdr->entry_bytes_n; |
|
858 |
|
entries_bytes_n = hdr->entries_n * hdr->entry_bytes_n; |
|
859 |
|
entries_lbas_n = entries_bytes_n / blk_dev.logical_blk_bytes_n |
|
860 |
|
+ ((entries_bytes_n % blk_dev.logical_blk_bytes_n) == 0 |
|
861 |
|
? 0 : 1); |
|
862 |
|
entry_idx = 0; |
|
863 |
|
loop { |
|
864 |
|
u8 *src_entry; |
|
865 |
|
struct entry_t *dst_entry; |
|
866 |
|
u64 *p64; |
|
867 |
|
|
|
868 |
|
if (entry_idx == entries_n) |
|
869 |
|
break; |
|
870 |
|
src_entry = hdr->entries + entry_idx * hdr->entry_bytes_n; |
|
871 |
|
dst_entry = &entries[entry_idx]; |
|
872 |
|
|
|
873 |
|
guid_read(&dst_entry->type, src_entry); |
|
874 |
|
guid_read(&dst_entry->uniq, &src_entry[0x10]); |
|
875 |
|
p64 = (u64*)&src_entry[0x20]; |
|
876 |
|
dst_entry->first = le64toh(*p64); |
|
877 |
|
p64 = (u64*)&src_entry[0x28]; |
|
878 |
|
dst_entry->last = le64toh(*p64); |
|
879 |
|
p64 = (u64*)&src_entry[0x30]; |
|
880 |
|
dst_entry->attrs = le64toh(*p64); |
|
881 |
|
dst_entry->name = utf16_strdup((utf16*)&src_entry[0x38]); |
|
882 |
|
++entry_idx; |
|
883 |
|
} |
|
884 |
|
} |
|
885 |
|
STATIC void previous_gpt_load(void) |
|
886 |
|
{ |
|
887 |
|
hdrs.previous.primary.read_from_lba = 1; |
|
888 |
|
hdrs.previous.primary.str = "primary"; |
|
889 |
|
hdr_load(&hdrs.previous.primary); |
|
890 |
|
hdr_validate(&hdrs.previous.primary); |
|
891 |
|
if (hdrs.previous.primary.valid) { |
|
892 |
|
entries_load(&hdrs.previous.primary); |
|
893 |
|
if (hdrs.previous.primary.entries_valid) |
|
894 |
|
return; |
|
895 |
|
/* damn! we have a valid header but with invalid entries */ |
|
896 |
|
hdrs.previous.secondary.read_from_lba = |
|
897 |
|
hdrs.previous.primary.alternate_hdr_lba; |
|
898 |
|
hdrs.previous.secondary.str = "alternate from primary header"; |
|
899 |
|
} else { /* arg! try the device last lba */ |
|
900 |
|
hdrs.previous.secondary.read_from_lba = blk_dev.last_lba; |
|
901 |
|
hdrs.previous.secondary.str = "from device last lba"; |
|
902 |
|
} |
|
903 |
|
/* |
|
904 |
|
* here, something went wrong with the primary header. 2 cases: |
|
905 |
|
* - the primary header is ok but the entries are not, then we are |
|
906 |
|
* trying the alternate header from the primary header data. |
|
907 |
|
* - the primary header is nok, we are try to look for a secondary |
|
908 |
|
* header from the last lba of the device. |
|
909 |
|
*/ |
|
910 |
|
hdr_load(&hdrs.previous.secondary); |
|
911 |
|
hdr_validate(&hdrs.previous.secondary); |
|
912 |
|
if (hdrs.previous.secondary.valid) |
|
913 |
|
entries_load(&hdrs.previous.secondary); |
|
914 |
|
} |
|
915 |
|
STATIC void hdrs_usable_lbas_compute(void) |
|
916 |
|
{ |
|
917 |
|
/* protective mbr, hdr, entries */ |
|
918 |
|
hdrs.first_usable_lba = 0 + 2 + entries_lbas_n; |
|
919 |
|
/* hdr, entries */ |
|
920 |
|
hdrs.last_usable_lba = blk_dev.last_lba - 1 - entries_lbas_n; |
|
921 |
|
} |
|
922 |
|
STATIC void entries_reset(void) |
|
923 |
|
{ |
|
924 |
|
u32 i; |
|
925 |
|
utf16 zero; |
|
926 |
|
u32 entries_bytes_n; |
|
927 |
|
|
|
928 |
|
if (entries_n != 0) { |
|
929 |
|
i = 0; |
|
930 |
|
loop { /* the utf16 names */ |
|
931 |
|
if (i == entries_n) |
|
932 |
|
break; |
|
933 |
|
free(entries[i].name); |
|
934 |
|
++i; |
|
935 |
|
} |
|
936 |
|
free(entries); |
|
937 |
|
} |
|
938 |
|
/* actually 128 entries */ |
|
939 |
|
entries_n = ENTRIES_ARRAY_MIN_BYTES_N / ENTRY_BYTES_N; |
|
940 |
|
entries = calloc(entries_n, ENTRY_BYTES_N); |
|
941 |
|
entry_bytes_n = ENTRY_BYTES_N; |
|
942 |
|
|
|
943 |
|
zero = 0; |
|
944 |
|
i = 0; |
|
945 |
|
loop { |
|
946 |
|
if (i == entries_n) |
|
947 |
|
break; |
|
948 |
|
entries[i].name = utf16_strdup(&zero); |
|
949 |
|
++i; |
|
950 |
|
} |
|
951 |
|
entries_bytes_n = entries_n * entry_bytes_n; |
|
952 |
|
entries_lbas_n = entries_bytes_n / blk_dev.logical_blk_bytes_n |
|
953 |
|
+ (entries_bytes_n % entry_bytes_n == 0 ? 0 : 1); |
|
954 |
|
} |
|
955 |
|
/******************************************************************************/ |
|
956 |
|
STATIC void out_guid(struct guid_t *guid) |
|
957 |
|
{ |
|
958 |
|
u8 i; |
|
959 |
|
out_pf("%08x-%04x-%04x-%04x-", guid->blk_0, guid->blk_1, guid->blk_2, |
|
960 |
|
guid->blk_3); |
|
961 |
|
i = 0; |
|
962 |
|
loop { |
|
963 |
|
if (i == 6) |
|
964 |
|
break; |
|
965 |
|
out_pf("%02x", guid->blk_4[i]); |
|
966 |
|
++i; |
|
967 |
|
} |
|
968 |
|
} |
|
969 |
|
struct { |
|
970 |
|
struct guid_t guid; |
|
971 |
|
utf8 *name; |
|
972 |
|
} types[] = { |
|
973 |
|
[0].guid.blk_0 = 0xc12a7328, |
|
974 |
|
[0].guid.blk_1 = 0xf81f, |
|
975 |
|
[0].guid.blk_2 = 0x11d2, |
|
976 |
|
[0].guid.blk_3 = 0xba4b, |
|
977 |
|
[0].guid.blk_4 = {0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b}, |
|
978 |
|
[0].name = "EFI system", |
|
979 |
|
|
|
980 |
|
[1].guid.blk_0 = 0x4f68bce3, |
|
981 |
|
[1].guid.blk_1 = 0xe8cd, |
|
982 |
|
[1].guid.blk_2 = 0x4db1, |
|
983 |
|
[1].guid.blk_3 = 0x96e7, |
|
984 |
|
[1].guid.blk_4 = {0xfb, 0xca, 0xf9, 0x84, 0xb7, 0x09}, |
|
985 |
|
[1].name = "linux root x86_64", |
|
986 |
|
}; |
|
987 |
|
STATIC void types_show(void) |
|
988 |
|
{ |
|
989 |
|
u32 i; |
|
990 |
|
u32 n; |
|
991 |
|
|
|
992 |
|
n = ARRAY_N(types); |
|
993 |
|
i = 0; |
|
994 |
|
loop { |
|
995 |
|
if (i == n) |
|
996 |
|
break; |
|
997 |
|
out_pf("%"PRIu32": ", i + 1); |
|
998 |
|
out_guid(&types[i].guid); |
|
999 |
|
out_pf(" %s\n", types[i].name); |
|
1000 |
|
++i; |
|
1001 |
|
} |
|
1002 |
|
} |
|
1003 |
|
STATIC utf8 *type_guids_lookup_name(struct guid_t *guid) |
|
1004 |
|
{ |
|
1005 |
|
u32 i; |
|
1006 |
|
u32 n; |
|
1007 |
|
|
|
1008 |
|
n = ARRAY_N(types); |
|
1009 |
|
i = 0; |
|
1010 |
|
loop { |
|
1011 |
|
if (i == n) |
|
1012 |
|
break; |
|
1013 |
|
if (memcmp(guid, &types[i].guid, sizeof(*guid)) == 0) |
|
1014 |
|
return types[i].name; |
|
1015 |
|
++i; |
|
1016 |
|
} |
|
1017 |
|
return "unknown"; |
|
1018 |
|
} |
|
1019 |
|
STATIC void entry_show(u32 idx, struct entry_t *entry) |
|
1020 |
|
{ |
|
1021 |
|
utf16 *pc; |
|
1022 |
|
utf8 *type_str; |
|
1023 |
|
|
|
1024 |
|
out_pf("%"PRIu32": %"PRIu64" %"PRIu64" ", idx + 1, entry->first, entry->last); |
|
1025 |
|
out_guid(&entry->type); |
|
1026 |
|
type_str = type_guids_lookup_name(&entry->type); |
|
1027 |
|
out_pf("(%s)", type_str); |
|
1028 |
|
out_pf("\n "); |
|
1029 |
|
out_guid(&entry->uniq); |
|
1030 |
|
out_pf(" "); |
|
1031 |
|
out_pf("0x%"PRIx64" \"", entry->attrs); |
|
1032 |
|
pc = entry->name; |
|
1033 |
|
loop { |
|
1034 |
|
u16 c; |
|
1035 |
|
|
|
1036 |
|
c = le16toh(*pc); |
|
1037 |
|
if (c == 0) |
|
1038 |
|
break; |
|
1039 |
|
/* keep it simple */ |
|
1040 |
|
if ((u16)'0' <= c && c <= (u16)'9' |
|
1041 |
|
&& (u16)'A' <= c && c <= (u16)'Z' |
|
1042 |
|
&& (u16)'a' <= c && c <= (u16)'z') |
|
1043 |
|
out_pf("%c", c); |
|
1044 |
|
else |
|
1045 |
|
out_pf("�"); |
|
1046 |
|
++pc; |
|
1047 |
|
} |
|
1048 |
|
out_pf("\"\n"); |
|
1049 |
|
} |
|
1050 |
|
STATIC bool guid_is_zero(struct guid_t *guid) |
|
1051 |
|
{ |
|
1052 |
|
u8 *b; |
|
1053 |
|
u8 *last; |
|
1054 |
|
|
|
1055 |
|
b = (u8*)guid; |
|
1056 |
|
last = b + sizeof(*guid) - 1; |
|
1057 |
|
loop { |
|
1058 |
|
if (*b != 0) |
|
1059 |
|
return false; |
|
1060 |
|
if (b == last) |
|
1061 |
|
return true; |
|
1062 |
|
++b; |
|
1063 |
|
} |
|
1064 |
|
} |
|
1065 |
|
STATIC bool entry_is_used(u32 idx) |
|
1066 |
|
{ |
|
1067 |
|
struct entry_t *entry; |
|
1068 |
|
|
|
1069 |
|
entry = &entries[idx]; |
|
1070 |
|
if ( guid_is_zero(&entry->type) |
|
1071 |
|
&& guid_is_zero(&entry->uniq) |
|
1072 |
|
&& entry->first == 0 |
|
1073 |
|
&& entry->last == 0 |
|
1074 |
|
&& entry->attrs == 0 |
|
1075 |
|
&& entry->name[0] == 0) { |
|
1076 |
|
return false; |
|
1077 |
|
} |
|
1078 |
|
return true; |
|
1079 |
|
} |
|
1080 |
|
STATIC void entry_delete(u32 idx) |
|
1081 |
|
{ |
|
1082 |
|
struct entry_t *entry; |
|
1083 |
|
utf16 empty_str; |
|
1084 |
|
|
|
1085 |
|
empty_str = 0; |
|
1086 |
|
entry = &entries[idx]; |
|
1087 |
|
free(entry->name); |
|
1088 |
|
memset(entry, 0, sizeof(*entry)); |
|
1089 |
|
entry->name = utf16_strdup(&empty_str); |
|
1090 |
|
} |
|
1091 |
|
STATIC void entries_show(void) |
|
1092 |
|
{ |
|
1093 |
|
u32 entry_idx; |
|
1094 |
|
|
|
1095 |
|
if (entries_n == 0) { |
|
1096 |
|
out_pf("no partition entries\n"); |
|
1097 |
|
return; |
|
1098 |
|
} else { |
|
1099 |
|
out_bold_pf("array of partition entries has %"PRIu32" slots:\n", entries_n); |
|
1100 |
|
} |
|
1101 |
|
entry_idx = 0; |
|
1102 |
|
out_bold_pf("slot / first / last / type(guid) \n"); |
|
1103 |
|
out_bold_pf(" uniq_guid / attributes / name\n"); |
|
1104 |
|
loop { |
|
1105 |
|
if (entry_idx == entries_n) |
|
1106 |
|
break; |
|
1107 |
|
if (entry_is_used(entry_idx)) |
|
1108 |
|
entry_show(entry_idx, &entries[entry_idx]); |
|
1109 |
|
++entry_idx; |
|
1110 |
|
} |
|
1111 |
|
} |
|
1112 |
|
STATIC void main_menu_show(void) |
|
1113 |
|
{ |
|
1114 |
|
out_pf("\ |
|
1115 |
|
Command / Action\n\ |
|
1116 |
|
p print the partition entries\n\ |
|
1117 |
|
n new partition entry\n\ |
|
1118 |
|
d delete a partition entry\n\ |
|
1119 |
|
h print the header\n\ |
|
1120 |
|
u change disk guid\n\ |
|
1121 |
|
w write and quit\n\ |
|
1122 |
|
q quit without saving\n"); |
|
1123 |
|
} |
|
1124 |
|
STATIC u8 input_line[BUFSIZ]; |
|
1125 |
|
STATIC void *(*input_state)(size_t lf); |
|
1126 |
|
/* list of states -- start */ |
|
1127 |
|
STATIC void *state_main_menu(size_t lf); |
|
1128 |
|
STATIC void *state_delete_entry(size_t lf); |
|
1129 |
|
STATIC void *state_change_disk_guid(size_t lf); |
|
1130 |
|
STATIC void *state_edit_entry(size_t lf); |
|
1131 |
|
STATIC void *state_edit_entry_substate_first_lba(size_t lf); |
|
1132 |
|
STATIC void *state_edit_entry_substate_last_lba(size_t lf); |
|
1133 |
|
STATIC void *state_edit_entry_substate_type(size_t lf); |
|
1134 |
|
STATIC void *state_edit_entry_substate_uniq_quid(size_t lf); |
|
1135 |
|
STATIC void *state_edit_entry_substate_attrs(size_t lf); |
|
1136 |
|
/* list of states -- end */ |
|
1137 |
|
STATIC struct { |
|
1138 |
|
u32 num; |
|
1139 |
|
u64 first_lba_default; |
|
1140 |
|
u64 first_lba; |
|
1141 |
|
u64 last_lba_default; |
|
1142 |
|
u64 last_lba; |
|
1143 |
|
u32 type; |
|
1144 |
|
struct guid_t uniq; |
|
1145 |
|
u64 attrs; |
|
1146 |
|
} edit_entry; |
|
1147 |
|
/*{{{ prompts */ |
|
1148 |
|
STATIC void edit_entry_attrs_prompt(void) |
|
1149 |
|
{ |
|
1150 |
|
out_pf("attributes as an hexadecimal number (default to 0x0): "); |
|
1151 |
|
} |
|
1152 |
|
STATIC void edit_entry_uniq_guid_prompt(void) |
|
1153 |
|
{ |
|
1154 |
|
out_pf("uniq guid (r to randomize): "); |
|
1155 |
|
} |
|
1156 |
|
STATIC void edit_entry_type_prompt(void) |
|
1157 |
|
{ |
|
1158 |
|
out_pf("number of the type of partition (l for the list): "); |
|
1159 |
|
} |
|
1160 |
|
STATIC void main_menu_prompt(void) |
|
1161 |
|
{ |
|
1162 |
|
out_pf("command (m for help): "); |
|
1163 |
|
} |
|
1164 |
|
STATIC void delete_entry_prompt(void) |
|
1165 |
|
{ |
|
1166 |
|
out_pf("number of the partition entry to delete: "); |
|
1167 |
|
} |
|
1168 |
|
STATIC void edit_entry_last_lba_prompt(void) |
|
1169 |
|
{ |
|
1170 |
|
out_pf("last logical block lba (default to %"PRIu64"): ", |
|
1171 |
|
edit_entry.last_lba_default); |
|
1172 |
|
} |
|
1173 |
|
STATIC void edit_entry_prompt(void) |
|
1174 |
|
{ |
|
1175 |
|
out_pf("partition entry number (1-%"PRIu32"): ", entries_n); |
|
1176 |
|
} |
|
1177 |
|
STATIC void edit_entry_first_lba_prompt(void) |
|
1178 |
|
{ |
|
1179 |
|
out_pf("first logical block lba (default to %"PRIu64"): ", |
|
1180 |
|
edit_entry.first_lba_default); |
|
1181 |
|
} |
|
1182 |
|
STATIC void change_disk_guid_prompt(void) |
|
1183 |
|
{ |
|
1184 |
|
out_pf("current disk guid is "); |
|
1185 |
|
out_guid(&hdrs.disk_guid); |
|
1186 |
|
out_pf("\nnew one (r to randomize): "); |
|
1187 |
|
} |
|
1188 |
|
/*}}} prompts -- end */ |
|
1189 |
|
STATIC void first_lba_default_select(void) |
|
1190 |
|
{ |
|
1191 |
|
u32 idx; |
|
1192 |
|
|
|
1193 |
|
/* mbr, header, entries. Should not need to cap this */ |
|
1194 |
|
edit_entry.first_lba_default = hdrs.first_usable_lba; |
|
1195 |
|
if (edit_entry.num == 1) |
|
1196 |
|
return; |
|
1197 |
|
/* num >= 2, idx >= 1 */ |
|
1198 |
|
idx = edit_entry.num - 2; |
|
1199 |
|
/* |
|
1200 |
|
* we are going "backward" to locate the right before used entry, then |
|
1201 |
|
* we will use the last lba from this entry to compute the first |
|
1202 |
|
* lba for this one |
|
1203 |
|
*/ |
|
1204 |
|
loop { |
|
1205 |
|
if (entry_is_used(idx)) { |
|
1206 |
|
edit_entry.first_lba_default = entries[idx].last + 1; |
|
1207 |
|
/* hard capping */ |
|
1208 |
|
if (edit_entry.first_lba_default < hdrs.first_usable_lba) |
|
1209 |
|
edit_entry.first_lba_default = hdrs.first_usable_lba; |
|
1210 |
|
if (edit_entry.first_lba_default > hdrs.last_usable_lba) |
|
1211 |
|
edit_entry.first_lba_default = hdrs.last_usable_lba; |
|
1212 |
|
break; |
|
1213 |
|
} |
|
1214 |
|
if (idx == 0) |
|
1215 |
|
break; |
|
1216 |
|
idx--; |
|
1217 |
|
} |
|
1218 |
|
} |
|
1219 |
|
STATIC void last_lba_default_select(void) |
|
1220 |
|
{ |
|
1221 |
|
u32 idx; |
|
1222 |
|
|
|
1223 |
|
edit_entry.last_lba_default = hdrs.last_usable_lba; |
|
1224 |
|
if (edit_entry.num == entries_n) |
|
1225 |
|
return; |
|
1226 |
|
/* num <= entries_n - 1, idx <= entries_n - 2 */ |
|
1227 |
|
idx = edit_entry.num; |
|
1228 |
|
/* |
|
1229 |
|
* we are going forward to reach the first used entry and then use |
|
1230 |
|
* the lba right before its first lba. |
|
1231 |
|
*/ |
|
1232 |
|
loop { |
|
1233 |
|
if (idx == entries_n) |
|
1234 |
|
break; |
|
1235 |
|
if (entry_is_used(idx)) { |
|
1236 |
|
edit_entry.last_lba_default = entries[idx].first - 1; |
|
1237 |
|
/* hard capping */ |
|
1238 |
|
if (edit_entry.last_lba_default < hdrs.first_usable_lba) |
|
1239 |
|
edit_entry.last_lba_default = hdrs.first_usable_lba; |
|
1240 |
|
if (edit_entry.last_lba_default > hdrs.last_usable_lba) |
|
1241 |
|
edit_entry.last_lba_default = hdrs.last_usable_lba; |
|
1242 |
|
break; |
|
1243 |
|
} |
|
1244 |
|
++idx; |
|
1245 |
|
} |
|
1246 |
|
} |
|
1247 |
|
STATIC void *hdr_show(void) |
|
1248 |
|
{ |
|
1249 |
|
out_pf("header:\ndisk guid "); |
|
1250 |
|
out_guid(&hdrs.disk_guid); |
|
1251 |
|
out_pf("\nfirst usable lba %"PRIu64"\n", hdrs.first_usable_lba); |
|
1252 |
|
out_pf("last usable lba %"PRIu64"\n", hdrs.last_usable_lba); |
|
1253 |
|
out_pf("%s last lba is %"PRIu64"\n", blk_dev.path, blk_dev.last_lba); |
|
1254 |
|
} |
|
1255 |
|
STATIC void guid_randomize(struct guid_t *guid) |
|
1256 |
|
{ |
|
1257 |
|
int fd; |
|
1258 |
|
|
|
1259 |
|
fd = open("/dev/urandom", O_RDONLY); |
|
1260 |
|
if (fd == -1) { |
|
1261 |
|
warning_pf("unable to open /dev/urandom for guid randomization\n"); |
|
1262 |
|
return; |
|
1263 |
|
} |
|
1264 |
|
if (!read_full(fd, guid, sizeof(*guid))) |
|
1265 |
|
warning_pf("something went wrong while reading from /dev/urandom, the guid is probably corrupted\n"); |
|
1266 |
|
close(fd); |
|
1267 |
|
} |
|
1268 |
|
/* best effort */ |
|
1269 |
|
STATIC void guid_read_from_input(struct guid_t *guid, size_t lf) |
|
1270 |
|
{ |
|
1271 |
|
u8 *blk_start; |
|
1272 |
|
u8 *blk_end; |
|
1273 |
|
u8 save; |
|
1274 |
|
u8 *end; |
|
1275 |
|
|
|
1276 |
|
input_line[lf] = 0; |
|
1277 |
|
end = input_line + lf; |
|
1278 |
|
|
|
1279 |
|
blk_start = input_line; |
|
1280 |
|
blk_end = strchr(blk_start, '-'); |
|
1281 |
|
if (blk_end == 0) |
|
1282 |
|
return; |
|
1283 |
|
*blk_end = 0; |
|
1284 |
|
guid->blk_0 = (u32)strtou64(blk_start, 0, 16); |
|
1285 |
|
blk_start = blk_end + 1; |
|
1286 |
|
if (blk_start >= end) |
|
1287 |
|
return; |
|
1288 |
|
blk_end = strchr(blk_start, '-'); |
|
1289 |
|
if (blk_end == 0) |
|
1290 |
|
return; |
|
1291 |
|
*blk_end = 0; |
|
1292 |
|
guid->blk_1 = (u16)strtou64(blk_start, 0, 16); |
|
1293 |
|
blk_start = blk_end + 1; |
|
1294 |
|
if (blk_start >= end) |
|
1295 |
|
return; |
|
1296 |
|
blk_end = strchr(blk_start, '-'); |
|
1297 |
|
if (blk_end == 0) |
|
1298 |
|
return; |
|
1299 |
|
*blk_end = 0; |
|
1300 |
|
guid->blk_2 = (u16)strtou64(blk_start, 0, 16); |
|
1301 |
|
blk_start = blk_end + 1; |
|
1302 |
|
if (blk_start >= end) |
|
1303 |
|
return; |
|
1304 |
|
blk_end = strchr(blk_start, '-'); |
|
1305 |
|
if (blk_end == 0) |
|
1306 |
|
return; |
|
1307 |
|
*blk_end = 0; |
|
1308 |
|
guid->blk_3 = (u16)strtou64(blk_start, 0, 16); |
|
1309 |
|
/* blk_4 */ |
|
1310 |
|
blk_start = blk_end + 1; |
|
1311 |
|
if (blk_start >= end) |
|
1312 |
|
return; |
|
1313 |
|
blk_end = blk_start + 12; /* 6 bytes */ |
|
1314 |
|
if (blk_end > end) |
|
1315 |
|
return; |
|
1316 |
|
save = blk_start[2]; |
|
1317 |
|
blk_start[2] = 0; |
|
1318 |
|
guid->blk_4[0] = (u8)strtou64(&blk_start[0], 0, 16); |
|
1319 |
|
blk_start[2] = save; |
|
1320 |
|
|
|
1321 |
|
save = blk_start[4]; |
|
1322 |
|
blk_start[4] = 0; |
|
1323 |
|
guid->blk_4[1] = (u8)strtou64(&blk_start[2], 0, 16); |
|
1324 |
|
blk_start[4] = save; |
|
1325 |
|
|
|
1326 |
|
save = blk_start[6]; |
|
1327 |
|
blk_start[6] = 0; |
|
1328 |
|
guid->blk_4[2] = (u8)strtou64(&blk_start[4], 0, 16); |
|
1329 |
|
blk_start[6] = save; |
|
1330 |
|
|
|
1331 |
|
save = blk_start[8]; |
|
1332 |
|
blk_start[8] = 0; |
|
1333 |
|
guid->blk_4[3] = (u8)strtou64(&blk_start[6], 0, 16); |
|
1334 |
|
blk_start[8] = save; |
|
1335 |
|
|
|
1336 |
|
save = blk_start[10]; |
|
1337 |
|
blk_start[10] = 0; |
|
1338 |
|
guid->blk_4[4] = (u8)strtou64(&blk_start[8], 0, 16); |
|
1339 |
|
blk_start[10] = save; |
|
1340 |
|
|
|
1341 |
|
guid->blk_4[5] = (u8)strtou64(&blk_start[10], 0, 16); |
|
1342 |
|
} |
|
1343 |
|
STATIC void *edit_entry_to_entries(void) |
|
1344 |
|
{ |
|
1345 |
|
struct entry_t *dst_entry; |
|
1346 |
|
|
|
1347 |
|
dst_entry = &entries[edit_entry.num - 1]; |
|
1348 |
|
memcpy(&dst_entry->type, &types[edit_entry.type - 1].guid, |
|
1349 |
|
sizeof(dst_entry->type)); |
|
1350 |
|
memcpy(&dst_entry->uniq, &edit_entry.uniq, sizeof(dst_entry->uniq)); |
|
1351 |
|
dst_entry->first = edit_entry.first_lba; |
|
1352 |
|
dst_entry->last = edit_entry.last_lba; |
|
1353 |
|
dst_entry->attrs = edit_entry.attrs; |
|
1354 |
|
/* don't support name input yet */ |
|
1355 |
|
} |
|
1356 |
|
STATIC void gpt_write(void) |
|
1357 |
|
{ |
|
1358 |
|
entries_serialized_array_gen(); |
|
1359 |
|
/* crc32 on exactly the entries array size, not lba bounded */ |
|
1360 |
|
entries_serialized_array_crc32 = 0; |
|
1361 |
|
le_crc32_update(entries_serialized_array, entry_bytes_n * entries_n, |
|
1362 |
|
&entries_serialized_array_crc32); |
|
1363 |
|
hdr_primary_serialized_gen(); |
|
1364 |
|
hdr_secondary_serialized_gen(); |
|
1365 |
|
protective_mbr_gen(); |
|
1366 |
|
protective_mbr_write(); |
|
1367 |
|
hdr_primary_serialized_write(); |
|
1368 |
|
hdr_secondary_serialized_write(); |
|
1369 |
|
entries_serialized_array_primary_write(); |
|
1370 |
|
entries_serialized_array_secondary_write(); |
|
1371 |
|
} |
|
1372 |
|
/*{{{ states */ |
|
1373 |
|
STATIC void *state_edit_entry_substate_attrs(size_t lf) |
|
1374 |
|
{ |
|
1375 |
|
if (lf == 0) { |
|
1376 |
|
edit_entry.attrs = 0; |
|
1377 |
|
goto exit; |
|
1378 |
|
} |
|
1379 |
|
input_line[lf] = 0; |
|
1380 |
|
edit_entry.attrs = strtou64(input_line, 0, 16); |
|
1381 |
|
exit: |
|
1382 |
|
/* |
|
1383 |
|
* TODO: don't want to use iconv, will implement an utf8 to utf16 |
|
1384 |
|
* converter another time. |
|
1385 |
|
*/ |
|
1386 |
|
edit_entry_to_entries(); |
|
1387 |
|
main_menu_prompt(); |
|
1388 |
|
return state_main_menu; |
|
1389 |
|
} |
|
1390 |
|
STATIC void *state_edit_entry_substate_uniq_quid(size_t lf) |
|
1391 |
|
{ |
|
1392 |
|
if (lf == 1 && input_line[0] == 'r') { |
|
1393 |
|
guid_randomize(&edit_entry.uniq); |
|
1394 |
|
out_pf("generated guid is : "); |
|
1395 |
|
goto exit; |
|
1396 |
|
} |
|
1397 |
|
guid_read_from_input(&edit_entry.uniq, lf); |
|
1398 |
|
out_pf("read guid is : "); |
|
1399 |
|
exit: |
|
1400 |
|
out_guid(&edit_entry.uniq); |
|
1401 |
|
out_pf("\n"); |
|
1402 |
|
edit_entry_attrs_prompt(); |
|
1403 |
|
return state_edit_entry_substate_attrs; |
|
1404 |
|
} |
|
1405 |
|
STATIC void *state_edit_entry_substate_type(size_t lf) |
|
1406 |
|
{ |
|
1407 |
|
if (lf == 1 && input_line[0] == 'l') { |
|
1408 |
|
types_show(); |
|
1409 |
|
edit_entry_type_prompt(); |
|
1410 |
|
return state_edit_entry_substate_type; |
|
1411 |
|
} |
|
1412 |
|
input_line[lf] = 0; |
|
1413 |
|
edit_entry.type = (u32)strtou64(input_line, 0, 10); |
|
1414 |
|
if (edit_entry.type == 0 || edit_entry.type > ARRAY_N(types)) { |
|
1415 |
|
warning_pf("invalid type number\n"); |
|
1416 |
|
edit_entry_type_prompt(); |
|
1417 |
|
return state_edit_entry_substate_type; |
|
1418 |
|
} |
|
1419 |
|
edit_entry_uniq_guid_prompt(); |
|
1420 |
|
return state_edit_entry_substate_uniq_quid; |
|
1421 |
|
} |
|
1422 |
|
STATIC void *state_edit_entry_substate_last_lba(size_t lf) |
|
1423 |
|
{ |
|
1424 |
|
if (lf == 0) |
|
1425 |
|
edit_entry.last_lba = edit_entry.last_lba_default; |
|
1426 |
|
else { |
|
1427 |
|
input_line[lf] = 0; |
|
1428 |
|
edit_entry.last_lba = strtou64(input_line, 0, 10); |
|
1429 |
|
} |
|
1430 |
|
edit_entry_type_prompt(); |
|
1431 |
|
return state_edit_entry_substate_type; |
|
1432 |
|
} |
|
1433 |
|
STATIC void *state_edit_entry_substate_first_lba(size_t lf) |
|
1434 |
|
{ |
|
1435 |
|
if (lf == 0) { |
|
1436 |
|
edit_entry.first_lba = edit_entry.first_lba_default; |
|
1437 |
|
} else { |
|
1438 |
|
input_line[lf] = 0; |
|
1439 |
|
edit_entry.first_lba = strtou64(input_line, 0, 10); |
|
1440 |
|
} |
|
1441 |
|
last_lba_default_select(); |
|
1442 |
|
edit_entry_last_lba_prompt(); |
|
1443 |
|
return state_edit_entry_substate_last_lba; |
|
1444 |
|
} |
|
1445 |
|
STATIC void *state_edit_entry(size_t lf) |
|
1446 |
|
{ |
|
1447 |
|
input_line[lf] = 0; |
|
1448 |
|
edit_entry.num = (u32)strtou64(input_line, 0, 10); |
|
1449 |
|
if (1 <= edit_entry.num && edit_entry.num <= entries_n) { |
|
1450 |
|
first_lba_default_select(); |
|
1451 |
|
edit_entry_first_lba_prompt(); |
|
1452 |
|
return state_edit_entry_substate_first_lba; |
|
1453 |
|
} else |
|
1454 |
|
warning_pf("%"PRIu32" is an invalid partition entry number\n", edit_entry.num); |
|
1455 |
|
main_menu_prompt(); |
|
1456 |
|
return state_main_menu; |
|
1457 |
|
} |
|
1458 |
|
STATIC void *state_delete_entry(size_t lf) |
|
1459 |
|
{ |
|
1460 |
|
u8 *end; |
|
1461 |
|
u32 entry_num; |
|
1462 |
|
|
|
1463 |
|
input_line[lf] = 0; |
|
1464 |
|
entry_num = (u32)strtou64(input_line, 0, 10); |
|
1465 |
|
if (1 <= entry_num && entry_num <= entries_n) { |
|
1466 |
|
out_bold_pf("deleting partition entry %"PRIu64"\n", entry_num); |
|
1467 |
|
entry_delete((u32)(entry_num - 1)); |
|
1468 |
|
} else |
|
1469 |
|
out_bold_pf("partition number out of range %"PRIu64"\n", entry_num); |
|
1470 |
|
main_menu_prompt(); |
|
1471 |
|
return state_main_menu; |
|
1472 |
|
} |
|
1473 |
|
STATIC void *state_change_disk_guid(size_t lf) |
|
1474 |
|
{ |
|
1475 |
|
if (lf == 1) { |
|
1476 |
|
if (input_line[0] == 'r') { |
|
1477 |
|
guid_randomize(&hdrs.disk_guid); |
|
1478 |
|
out_pf("randomized disk guid is "); |
|
1479 |
|
} |
|
1480 |
|
} else { |
|
1481 |
|
guid_read_from_input(&hdrs.disk_guid, lf); |
|
1482 |
|
out_pf("read disk guid is "); |
|
1483 |
|
} |
|
1484 |
|
out_guid(&hdrs.disk_guid); |
|
1485 |
|
out_pf("\n"); |
|
1486 |
|
main_menu_prompt(); |
|
1487 |
|
return state_main_menu; |
|
1488 |
|
} |
|
1489 |
|
STATIC void *state_main_menu(size_t lf) |
|
1490 |
|
{ |
|
1491 |
|
if (lf == 1) { |
|
1492 |
|
switch(input_line[0]) { |
|
1493 |
|
case 'q': |
|
1494 |
|
out_pf("quit\n"); |
|
1495 |
|
exit(0); |
|
1496 |
|
case 'm': |
|
1497 |
|
main_menu_show(); |
|
1498 |
|
break; |
|
1499 |
|
case 'p': |
|
1500 |
|
entries_show(); |
|
1501 |
|
break; |
|
1502 |
|
case 'h': |
|
1503 |
|
hdr_show(); |
|
1504 |
|
break; |
|
1505 |
|
case 'd': |
|
1506 |
|
delete_entry_prompt(); |
|
1507 |
|
return state_delete_entry; |
|
1508 |
|
case 'n': |
|
1509 |
|
edit_entry_prompt(); |
|
1510 |
|
return state_edit_entry; |
|
1511 |
|
case 'u': |
|
1512 |
|
change_disk_guid_prompt(); |
|
1513 |
|
return state_change_disk_guid; |
|
1514 |
|
case 'w': |
|
1515 |
|
gpt_write(); |
|
1516 |
|
exit(0); |
|
1517 |
|
default: |
|
1518 |
|
break; |
|
1519 |
|
} |
|
1520 |
|
} |
|
1521 |
|
main_menu_prompt(); |
|
1522 |
|
return state_main_menu; |
|
1523 |
|
} |
|
1524 |
|
/*}}} states -- end */ |
|
1525 |
|
/* end is the index of the byte past the last read byte */ |
|
1526 |
|
STATIC size_t input_line_consume(size_t lf, size_t end) |
|
1527 |
|
{ |
|
1528 |
|
input_state = input_state(lf); |
|
1529 |
|
|
|
1530 |
|
/* update the input line buffer and offsets */ |
|
1531 |
|
if (lf == (BUFSIZ - 1)) { /* lf is the last char in our line buffer */ |
|
1532 |
|
memset(input_line, 0, BUFSIZ); |
|
1533 |
|
return 0; |
|
1534 |
|
} |
|
1535 |
|
memmove(input_line, input_line + lf + 1, end - (lf + 1)); |
|
1536 |
|
return end - (lf + 1); |
|
1537 |
|
} |
|
1538 |
|
STATIC void input_line_loop(void) |
|
1539 |
|
{ |
|
1540 |
|
bool discarding; |
|
1541 |
|
size_t end; |
|
1542 |
|
|
|
1543 |
|
end = 0; |
|
1544 |
|
memset(input_line, 0, BUFSIZ); |
|
1545 |
|
discarding = false; |
|
1546 |
|
input_state = state_main_menu; |
|
1547 |
|
main_menu_prompt(); |
|
1548 |
|
loop { |
|
1549 |
|
int r; |
|
1550 |
|
size_t lf; |
|
1551 |
|
|
|
1552 |
|
errno = 0; |
|
1553 |
|
r = read(0, &input_line[end], BUFSIZ - end); |
|
1554 |
|
if (r == -1) { |
|
1555 |
|
if (errno == EINTR) |
|
1556 |
|
continue; |
|
1557 |
|
error_pf("error reading input line from standard input\n"); |
|
1558 |
|
} |
|
1559 |
|
lf = end; |
|
1560 |
|
end += (size_t)r; |
|
1561 |
|
loop { /* scan what was read for lf */ |
|
1562 |
|
if (lf == end) |
|
1563 |
|
break; |
|
1564 |
|
if (input_line[lf] == '\n') { |
|
1565 |
|
if (discarding) { |
|
1566 |
|
discarding = false; |
|
1567 |
|
end = 0; |
|
1568 |
|
break; |
|
1569 |
|
} |
|
1570 |
|
end = input_line_consume(lf, end); |
|
1571 |
|
break; |
|
1572 |
|
} |
|
1573 |
|
++lf; |
|
1574 |
|
} |
|
1575 |
|
if (end == BUFSIZ) { |
|
1576 |
|
if (!discarding) { |
|
1577 |
|
out_pf("your input line is too long, discarding...\n"); |
|
1578 |
|
discarding = true; |
|
1579 |
|
} |
|
1580 |
|
end = 0; |
|
1581 |
|
} |
|
1582 |
|
} |
|
1583 |
|
} |
|
1584 |
|
STATIC void init_once(void) |
|
1585 |
|
{ |
|
1586 |
|
le_crc32_tbl_gen(); |
|
1587 |
|
colors_on = true; |
|
1588 |
|
load_previous_gpt = true; |
|
1589 |
|
entries = 0; |
|
1590 |
|
entries_n = 0; |
|
1591 |
|
memset(&hdrs, 0, sizeof(hdrs)); |
|
1592 |
|
} |
|
1593 |
|
STATIC void usage(void) |
|
1594 |
|
{ |
|
1595 |
|
BOLD; |
|
1596 |
|
out_pf("\ |
|
1597 |
|
nyangpt: line input oriented minimal GPT partition creator\n\ |
|
1598 |
|
\n\ |
|
1599 |
|
usage:\n\ |
|
1600 |
|
nyangpt [-nc] [-nl] [-h|--help][ [--] device_path\n\ |
|
1601 |
|
\n\ |
|
1602 |
|
-nc: disable ANSI terminal colors\n\ |
|
1603 |
|
-nl: don't load previous GPT partitions\n\ |
|
1604 |
|
-h|--help: this summary\n"); |
|
1605 |
|
RESTORE; |
|
1606 |
|
exit(0); |
|
1607 |
|
} |
|
1608 |
|
STATIC void options_parse(u32 argc, utf8 **argv) |
|
1609 |
|
{ |
|
1610 |
|
u32 arg; |
|
1611 |
|
bool no_more_options; |
|
1612 |
|
bool print_usage; |
|
1613 |
|
|
|
1614 |
|
if (argc == 1) |
|
1615 |
|
usage(); |
|
1616 |
|
arg = 1; |
|
1617 |
|
no_more_options = false; |
|
1618 |
|
print_usage = false; |
|
1619 |
|
blk_dev.path = 0; |
|
1620 |
|
loop { |
|
1621 |
|
if (arg == argc) |
|
1622 |
|
break; |
|
1623 |
|
if (no_more_options) { |
|
1624 |
|
if (blk_dev.path == 0) |
|
1625 |
|
blk_dev.path = argv[arg]; |
|
1626 |
|
} else if (strcmp(argv[arg], "--") == 0) { |
|
1627 |
|
no_more_options = true; |
|
1628 |
|
} else if (strcmp(argv[arg], "-nc") == 0) { |
|
1629 |
|
colors_on = false; |
|
1630 |
|
} else if (strcmp(argv[arg], "-nl") == 0) { |
|
1631 |
|
load_previous_gpt = false; |
|
1632 |
|
} else if (strcmp(argv[arg], "-h") == 0 |
|
1633 |
|
|| strcmp(argv[arg], "--help") == 0) { |
|
1634 |
|
print_usage = true; |
|
1635 |
|
} else { |
|
1636 |
|
if (blk_dev.path == 0) |
|
1637 |
|
blk_dev.path = argv[arg]; |
|
1638 |
|
} |
|
1639 |
|
++arg; |
|
1640 |
|
} |
|
1641 |
|
if (print_usage || blk_dev.path == 0) |
|
1642 |
|
usage(); |
|
1643 |
|
} |
|
1644 |
|
int nyangpt_main(int argc, utf8 **argv) |
|
1645 |
|
{ |
|
1646 |
|
u64 whole_dev_bytes_n; |
|
1647 |
|
u64 entries_bytes_n; |
|
1648 |
|
|
|
1649 |
|
init_once(); |
|
1650 |
|
options_parse(argc, argv); |
|
1651 |
|
out_pf("block device path is %s, opening...\n", blk_dev.path); |
|
1652 |
|
blk_dev.fd = open(blk_dev.path, O_RDWR | O_SYNC); |
|
1653 |
|
if (blk_dev.fd == -1) |
|
1654 |
|
error_pf("%s:unable to open\n", blk_dev.path); |
|
1655 |
|
out_pf("%s:opened\n", blk_dev.path); |
|
1656 |
|
|
|
1657 |
|
sysfs_infos_get(); |
|
1658 |
|
|
|
1659 |
|
whole_dev_bytes_n = blk_dev.sz_512_n * 512; |
|
1660 |
|
if ((whole_dev_bytes_n % blk_dev.logical_blk_bytes_n) != 0) |
|
1661 |
|
error_pf("%s: the whole device size %"PRIu64" is not a multiple of the logical block size %"PRIu64" bytes\n", whole_dev_bytes_n, blk_dev.logical_blk_bytes_n); |
|
1662 |
|
/* the total number of lba, -1 to get the offset of the last one */ |
|
1663 |
|
blk_dev.last_lba = blk_dev.sz_512_n * 512 / blk_dev.logical_blk_bytes_n - 1; |
|
1664 |
|
out_pf("%s:last lba is %"PRIu64"\n", blk_dev.path, blk_dev.last_lba); |
|
1665 |
|
|
|
1666 |
|
if (load_previous_gpt) { |
|
1667 |
|
previous_gpt_load(); |
|
1668 |
|
build_data_from_previous_gpt(); |
|
1669 |
|
} |
|
1670 |
|
/* |
|
1671 |
|
* Resizing the array of entries is expensive and dangerous, try to |
|
1672 |
|
* keep it constant as much as possible. |
|
1673 |
|
* If it was not initialized based from the previous gpt, init one |
|
1674 |
|
* with sane defaults. |
|
1675 |
|
*/ |
|
1676 |
|
if (entries_n == 0) |
|
1677 |
|
entries_reset(); |
|
1678 |
|
if (hdrs.bytes_n == 0) |
|
1679 |
|
hdrs.bytes_n = HDR_BYTES_N; |
|
1680 |
|
if (guid_is_zero(&hdrs.disk_guid)) |
|
1681 |
|
guid_randomize(&hdrs.disk_guid); |
|
1682 |
|
/* |
|
1683 |
|
* Once we have "an array of entries", the first and last usable |
|
1684 |
|
* lbas must be recomputed. |
|
1685 |
|
* We ignore the values from the previous gpt headers, we prefer |
|
1686 |
|
* to recompute them. |
|
1687 |
|
*/ |
|
1688 |
|
hdrs_usable_lbas_compute(); |
|
1689 |
|
input_line_loop(); |
|
1690 |
|
return 0; |
|
1691 |
|
} |
|
1692 |
|
/*{{{ preprocessor space cleanup */ |
|
1693 |
|
#undef ARRAY_N |
|
1694 |
|
#undef BLK_0 |
|
1695 |
|
#undef BLK_1 |
|
1696 |
|
#undef BLK_2 |
|
1697 |
|
#undef BLK_3 |
|
1698 |
|
#undef BLK_4 |
|
1699 |
|
#undef BOLD_RED |
|
1700 |
|
#undef BOLD_ORANGE |
|
1701 |
|
#undef BOLD |
|
1702 |
|
#undef RESTORE |
|
1703 |
|
#undef BOOT_SIGNATURE_0X55 |
|
1704 |
|
#undef BOOT_SIGNATURE_0XAA |
|
1705 |
|
#undef ENTRIES_ARRAY_MIN_BYTES_N |
|
1706 |
|
#undef ENTRY_BYTES_N |
|
1707 |
|
#undef HDR_BYTES_N |
|
1708 |
|
#undef HDR_REVISION |
|
1709 |
|
#undef HDR_SIGNATURE |
|
1710 |
|
#undef HDR_SIGNATURE_BYTES_N |
|
1711 |
|
#undef loop |
|
1712 |
|
#undef PART_0 |
|
1713 |
|
#undef s32 |
|
1714 |
|
#undef STATIC |
|
1715 |
|
#undef strtou64 |
|
1716 |
|
#undef u8 |
|
1717 |
|
#undef u16 |
|
1718 |
|
#undef u32 |
|
1719 |
|
#undef u64 |
|
1720 |
|
#undef utf16 |
|
1721 |
|
#undef utf8 |
|
1722 |
|
#undef X64_UTF8_BYTES_MAX |
|
1723 |
|
/*}}} preprocessor space cleanup -- end */ |
|
1724 |
|
/*{{{ namespace cleanup ------------------------------------------------------*/ |
|
1725 |
|
#undef nyangpt_blk_dev |
|
1726 |
|
#undef nyangpt_build_data_from_previous_gpt |
|
1727 |
|
#undef nyangpt_change_disk_guid_prompt |
|
1728 |
|
#undef nyangpt_colors_on |
|
1729 |
|
#undef nyangpt_delete_entry_prompt |
|
1730 |
|
#undef nyangpt_edit_entry |
|
1731 |
|
#undef nyangpt_edit_entry_attrs_prompt |
|
1732 |
|
#undef nyangpt_edit_entry_first_lba_prompt |
|
1733 |
|
#undef nyangpt_edit_entry_last_lba_prompt |
|
1734 |
|
#undef nyangpt_edit_entry_prompt |
|
1735 |
|
#undef nyangpt_edit_entry_to_entries |
|
1736 |
|
#undef nyangpt_edit_entry_type_prompt |
|
1737 |
|
#undef nyangpt_edit_entry_uniq_guid_prompt |
|
1738 |
|
#undef nyangpt_entries |
|
1739 |
|
#undef nyangpt_entries_lbas_n |
|
1740 |
|
#undef nyangpt_entries_load |
|
1741 |
|
#undef nyangpt_entries_n |
|
1742 |
|
#undef nyangpt_entries_reset |
|
1743 |
|
#undef nyangpt_entries_serialized_array |
|
1744 |
|
#undef nyangpt_entries_serialized_array_crc32 |
|
1745 |
|
#undef nyangpt_entries_serialized_array_gen |
|
1746 |
|
#undef nyangpt_entries_serialized_array_gen_entry |
|
1747 |
|
#undef nyangpt_entries_serialized_array_primary_write |
|
1748 |
|
#undef nyangpt_entries_serialized_array_secondary_write |
|
1749 |
|
#undef nyangpt_entries_show |
|
1750 |
|
#undef nyangpt_entry_bytes_n |
|
1751 |
|
#undef nyangpt_entry_delete |
|
1752 |
|
#undef nyangpt_entry_is_used |
|
1753 |
|
#undef nyangpt_entry_show |
|
1754 |
|
#undef nyangpt_entry_t |
|
1755 |
|
#undef nyangpt_error_pf |
|
1756 |
|
#undef nyangpt_first_lba_default_select |
|
1757 |
|
#undef nyangpt_gpt_write |
|
1758 |
|
#undef nyangpt_guid_is_zero |
|
1759 |
|
#undef nyangpt_guid_t |
|
1760 |
|
#undef nyangpt_guid_randomize |
|
1761 |
|
#undef nyangpt_guid_read |
|
1762 |
|
#undef nyangpt_guid_read_from_input |
|
1763 |
|
#undef nyangpt_guid_write |
|
1764 |
|
#undef nyangpt_hdr_load |
|
1765 |
|
#undef nyangpt_hdr_show |
|
1766 |
|
#undef nyangpt_hdr_primary_serialized |
|
1767 |
|
#undef nyangpt_hdr_primary_serialized_gen |
|
1768 |
|
#undef nyangpt_hdr_primary_serialized_write |
|
1769 |
|
#undef nyangpt_hdr_secondary_serialized |
|
1770 |
|
#undef nyangpt_hdr_secondary_serialized_gen |
|
1771 |
|
#undef nyangpt_hdr_secondary_serialized_write |
|
1772 |
|
#undef nyangpt_hdr_t |
|
1773 |
|
#undef nyangpt_hdr_validate |
|
1774 |
|
#undef nyangpt_hdrs |
|
1775 |
|
#undef nyangpt_hdrs_usable_lbas_compute |
|
1776 |
|
#undef nyangpt_init_once |
|
1777 |
|
#undef nyangpt_input_line |
|
1778 |
|
#undef nyangpt_input_line_consume |
|
1779 |
|
#undef nyangpt_input_line_loop |
|
1780 |
|
#undef nyangpt_input_state |
|
1781 |
|
#undef nyangpt_last_lba_default_select |
|
1782 |
|
#undef nyangpt_le_crc32_tbl_gen |
|
1783 |
|
#undef nyangpt_le_crc32_update |
|
1784 |
|
#undef nyangpt_load_previous_gpt |
|
1785 |
|
#undef nyangpt_main_menu_prompt |
|
1786 |
|
#undef nyangpt_main_menu_show |
|
1787 |
|
#undef nyangpt_options_parse |
|
1788 |
|
#undef nyangpt_out_bold_pf |
|
1789 |
|
#undef nyangpt_out_guid |
|
1790 |
|
#undef nyangpt_out_pf |
|
1791 |
|
#undef nyangpt_gpt_load |
|
1792 |
|
#undef nyangpt_protective_mbr |
|
1793 |
|
#undef nyangpt_protective_mbr_gen |
|
1794 |
|
#undef nyangpt_protective_mbr_write |
|
1795 |
|
#undef nyangpt_read_full |
|
1796 |
|
#undef nyangpt_state_change_disk_guid |
|
1797 |
|
#undef nyangpt_state_delete_entry |
|
1798 |
|
#undef nyangpt_state_edit_entry |
|
1799 |
|
#undef nyangpt_state_edit_entry_substate_attrs |
|
1800 |
|
#undef nyangpt_state_edit_entry_substate_first_lba |
|
1801 |
|
#undef nyangpt_state_edit_entry_substate_last_lba |
|
1802 |
|
#undef nyangpt_state_edit_entry_substate_type |
|
1803 |
|
#undef nyangpt_state_edit_entry_substate_uniq_quid |
|
1804 |
|
#undef nyangpt_state_main_menu |
|
1805 |
|
#undef nyangpt_sysfs_infos_get |
|
1806 |
|
#undef nyangpt_type_guids_lookup_name |
|
1807 |
|
#undef nyangpt_types |
|
1808 |
|
#undef nyangpt_types_show |
|
1809 |
|
#undef nyangpt_usage |
|
1810 |
|
#undef nyangpt_utf16_strdup |
|
1811 |
|
#undef nyangpt_warning_pf |
|
1812 |
|
#undef nyangpt_write_full |
|
1813 |
|
/*----------------------------------------------------------------------------*/ |
|
1814 |
|
#undef nyangpt_main |
|
1815 |
|
/*}}} namespace cleanup -- end -----------------------------------------------*/ |
|
1816 |
|
#endif |