sylware / nyanlinux (public) (License: AFFERO GPLv3) (since 2019-09-09) (hash sha1)
scripts for a lean, from scratch, amd hardware, linux distro
List of commits:
Subject Hash Author Date (UTC)
source oriented GPT partition creator 125bf2135b399a44290da5adc5b1d04657439f13 Sylvain BERTRAND 2021-05-08 21:29:40
npv:update 787edad0188d34d183b9e68afd029eb6dbf5fa5f Sylvain BERTRAND 2021-05-06 21:00:18
npv: update ad0c8f4e7d0f061507c4024fb7cf762cb0bfdc0e Sylvain BERTRAND 2021-05-06 18:40:48
actually, include steam binary support 30e944e10e13d186051a104378a81a1a068efc8d Sylvain BERTRAND 2021-04-30 18:59:05
x86 32bits cleanup 54fa4f7b32425ec6159a5fe52e96756309d42881 Sylvain BERTRAND 2021-04-29 16:25:32
steam note daf91e9f6f50ca931980716c9027d9bf85f4d94e Sylvain BERTRAND 2021-04-29 13:59:54
add 'temporary' x86 (32bits) cross compiler build scripts 342c07e1963dfeb3cea2ce8987db50bb3e1dd405 Sylvain BERTRAND 2021-04-28 18:58:39
gfx stack updates (vulkan is fixed) de1b4f6eacc3058698c6b34bf633e59a21c46da2 Sylvain BERTRAND 2021-04-28 12:54:18
gfx stack updates (vulkan still glitched, unable to contact the devs) 5aca72cfd01c96fe4be0880dc1f865486d6b54b1 Sylvain BERTRAND 2021-04-18 15:09:31
nyanmp: update aee5be44510f57052481d308ca35eb90ac5ab4cd Sylvain BERTRAND 2021-04-15 20:18:56
gfx stack updates (vulkan still glitched) b38a7af3ae29daaf6d338f3d8a180fcee70b0a3a Sylvain BERTRAND 2021-04-12 01:21:35
gfx stack updates (vulkan is broken for good) ba3f9ce81fe3265c2503b9185340d2fe6b13fe98 Sylvain BERTRAND 2021-03-28 17:25:19
gfx stack updates (vulkan is still broken but the fix is known) 254924d9552449a31eb57d5b82a17c0e1b7e6a6d Sylvain BERTRAND 2021-03-21 15:47:53
gfx stack updates (vulkan is broken but the fix is known) b114faec9a2954ca4d8324c7d259dcc589e04a46 Sylvain BERTRAND 2021-03-15 17:11:51
gfx stack update (llvm broke again) 0171e2b6d1c8cc2c2a72eea0b43f9003c89ea120 Sylvain BERTRAND 2021-02-28 18:55:39
gfx stack update 58e5a2b5c8ff2526d94c88719d16dc05e6f66a86 Sylvain BERTRAND 2021-02-18 23:31:03
a few cross binutils for assembly and ELF linking 58d8ea669edb9fdcffa89034309a2b16b6fb5cbb Sylvain BERTRAND 2021-02-10 18:51:53
gfx stack update 376f48701a1a58db5641714ed02a2e7420ffb090 Sylvain BERTRAND 2021-02-09 18:29:29
gfx stack update 2db0e6352df8b96203bcbd2e535b82621b27d76a Sylvain BERTRAND 2021-02-05 15:46:17
gfx stack update 5587e2cfcdc8883c13a5de278e77b9ae095a6750 Sylvain BERTRAND 2021-01-27 14:23:49
Commit 125bf2135b399a44290da5adc5b1d04657439f13 - source oriented GPT partition creator
Author: Sylvain BERTRAND
Author date (UTC): 2021-05-08 21:29
Committer name: Sylvain BERTRAND
Committer date (UTC): 2021-05-08 21:29
Parent(s): 787edad0188d34d183b9e68afd029eb6dbf5fa5f
Signer:
Signing key:
Signing status: N
Tree: a76c0fd81b27c5f96e32e2bc46d458dad794ac5e
File Lines added Lines deleted
files/nyangpt.c 682 0
File files/nyangpt.c added (mode: 100644) (index 0000000..dc5dcbd)
1 #ifndef NYANGPT_C
2 #define NYANGPT_C
3 /*
4 * Copyright 2021 Sylvain BERTRAND <sylvain.bertrand@legeek.net>
5 * LICENSE: GNU AFFERO GPLV3
6 */
7 /*
8 * quick and dirty, ultra minimal, source oriented, UEFI GPT partition creator
9 */
10 #include <stdarg.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <sys/stat.h>
17 #include <stdint.h>
18 #include <inttypes.h>
19 #include <endian.h>
20 #include <errno.h>
21 /*
22 * how to get pertinent device information from sysfs for GPT partitioning
23 *
24 * for a /dev/sdX block device:
25 * /sys/block/sdX/size = size of the device in blocks of 512 bytes (hardcoded)
26 * /sys/block/sdX/queue/logical_block_size = size in bytes of a logical block
27 * which is the size used by LBA (Logical Block Access) offsets used
28 * in GPT partitions
29 * /sys/block/sdX/queue/physical_block_size = size in bytes of a physical block
30 */
31 #define utf8 uint8_t
32 #define X64_UTF8_BYTES_MAX (sizeof("18446744073709551615") - 1)
33 /* meh */
34 #define strtou64 strtoul
35 #define u8 uint8_t
36 #define u16 uint16_t
37 #define u32 uint32_t
38 #define s32 int32_t
39 #define u64 uint64_t
40 #define loop for(;;)
41 /******************************************************************************/
42 /* stolen and cosmetized, not validated on big endian */
43 /* http://home.thep.lu.se/~bjorn/crc/ */
44 static u32 le_crc32_for_byte(u32 r)
45 {
46 u8 j;
47
48 j = 0;
49 loop {
50 if (j == 8)
51 break;
52 r = (r & 1 ? 0 : (u32)0xedb88320) ^ r >> 1;
53 ++j;
54 }
55 return r ^ (u32)0xff000000;
56 }
57 static u32 le_crc32_tbl[0x100];
58 static void le_crc32_tbl_gen(void)
59 {
60 u32 i;
61
62 i = 0;
63 loop {
64 if (i == 0x100)
65 break;
66 le_crc32_tbl[i] = le_crc32_for_byte(i);
67 ++i;
68 }
69 }
70 static void le_crc32_update(void *data, u64 bytes_n, u32* crc)
71 {
72 u64 i;
73
74 i = 0;
75 loop {
76 if (i == bytes_n)
77 break;
78 *crc = le_crc32_tbl[(u8)*crc ^ ((u8*)data)[i]] ^ *crc >> 8;
79 ++i;
80 }
81 }
82 /******************************************************************************/
83 /*----------------------------------------------------------------------------*/
84 static struct {
85 utf8 *path;
86 u64 sz_512_n;
87 u64 logical_blk_sz;
88 u64 physical_blk_sz;
89 int fd;
90 u64 last_lba;
91 } blk_dev;
92 /*----------------------------------------------------------------------------*/
93 static u8 *protective_mbr;
94 /* offsets */
95 #define BOOT_SIGNATURE_0X55 0x1fe
96 #define BOOT_SIGNATURE_0XAA 0x1ff
97 #define PART_0 0x1be
98 /*----------------------------------------------------------------------------*/
99 struct guid_t {
100 u32 blk_0;
101 u16 blk_1;
102 u16 blk_2;
103 u16 blk_3;
104 u8 blk_4[6];
105 };
106 #define BLK_0 0x0
107 #define BLK_1 0x4
108 #define BLK_2 0x6
109 #define BLK_3 0x8
110 #define BLK_4 0xa
111 struct entry_t {
112 struct guid_t type;
113 struct guid_t uniq;
114 u64 first;
115 u64 last;
116 u64 attrs;
117 /* utf-16 names? really?... */
118 };
119 #define ENTRIES_ARRAY_MIN_BYTES_N 16384 /* specs: minimum to book on the disk */
120 #define ENTRY_BYTES_N 0x80
121 /* make it at least 128MB */
122 static struct entry_t entry_efi_system =
123 {
124 .type.blk_0 = 0xc12a7328,
125 .type.blk_1 = 0xf81f,
126 .type.blk_2 = 0x11d2,
127 .type.blk_3 = 0xba4b,
128 .type.blk_4 = {0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b},
129
130 .uniq.blk_0 = 0xdeadbeef,
131 .uniq.blk_1 = 0x0000,
132 .uniq.blk_2 = 0x0000,
133 .uniq.blk_3 = 0x0000,
134 .uniq.blk_4 = {0x00, 0x0, 0x00, 0x00, 0x00, 0x01},
135
136 .first = 0x0000000000000022,
137 .last = 0x000000000004ffff,
138
139 .attrs = 0,
140 };
141 static struct entry_t entry_root =
142 {
143 /* linux root x86_64 GUID */
144 .type.blk_0 = 0x4f68bce3,
145 .type.blk_1 = 0xe8cd,
146 .type.blk_2 = 0x4db1,
147 .type.blk_3 = 0x96e7,
148 .type.blk_4 = {0xfb, 0xca, 0xf9, 0x84, 0xb7, 0x09},
149
150 .uniq.blk_0 = 0xdeadbeef,
151 .uniq.blk_1 = 0x0000,
152 .uniq.blk_2 = 0x0000,
153 .uniq.blk_3 = 0x0000,
154 .uniq.blk_4 = {0x00, 0x0, 0x00, 0x00, 0x00, 0x02},
155
156 /* everything else */
157 .first = 0x0000000000050000,
158 .last = 0x0, /* generated later */
159
160 .attrs = 0,
161 };
162 static struct entry_t *entries[2] = {
163 &entry_efi_system,
164 &entry_root,
165 };
166 static u8 entries_n = 2;
167 static u8 entries_lbas_n;
168 static u8 *entries_array;
169 static u32 entries_array_crc32;
170 /*----------------------------------------------------------------------------*/
171 struct hdrs_t { /* there are 2 headers, each must fit in a logical block */
172 u64 first_usable_lba;
173 u64 last_usable_lba;
174 struct guid_t disk;
175 };
176 static struct hdrs_t hdrs = {
177 .disk.blk_0 = 0xdeadbeef,
178 .disk.blk_1 = 0x0000,
179 .disk.blk_2 = 0x0000,
180 .disk.blk_3 = 0x0000,
181 .disk.blk_4 = {0x00, 0x0, 0x00, 0x00, 0x00, 0x00},
182 };
183 static u8 hdr_signature[8] = "EFI PART";
184 #define HDR_REVISION 0x00010000 /* 1.0 */
185 #define HDR_BYTES_N 0x5c /* 92 bytes */
186 static u8 *hdr_primary;
187 static u8 *hdr_secondary;
188 /*----------------------------------------------------------------------------*/
189 static utf8 *pf(utf8 *fmt,...)
190 {
191 va_list ap;
192 int r;
193 utf8 *r_str;
194
195 va_start(ap, fmt);
196 r = vsnprintf(0, 0, fmt, ap);
197 va_end(ap);
198
199 r_str = malloc(r + 1); /* we want a terminating 0 */
200
201 va_start(ap, fmt);
202 vsnprintf(r_str, r + 1, fmt, ap); /* has room for the terminating 0 */
203 va_end(ap);
204 return r_str;
205 }
206 /* brain damaged mixed-endian guid */
207 static void guid_write(void *dest, struct guid_t *src)
208 {
209 u8 *d;
210 u32 *p32;
211 u16 *p16;
212
213 d = (u8*)dest;
214
215 p32 = (u32*)d;
216 *p32 = htole32(src->blk_0); /* little endian */
217 d += 4;
218 p16 = (u16*)d;
219 *p16 = htole16(src->blk_1); /* little endian */
220 d += 2;
221 p16 = (u16*)d;
222 *p16 = htole16(src->blk_2); /* little endian */
223 d += 2;
224 p16 = (u16*)d;
225 *p16 = htobe16(src->blk_3); /* big endian */
226 d += 2;
227 d[0] = src->blk_4[0];
228 d[1] = src->blk_4[1];
229 d[2] = src->blk_4[2];
230 d[3] = src->blk_4[3];
231 d[4] = src->blk_4[4];
232 d[5] = src->blk_4[5];
233 }
234 static void sysfs_infos_get(void)
235 {
236 int fd;
237 int r;
238 utf8 val_str[X64_UTF8_BYTES_MAX + 1]; /* 0 terminating char */
239 utf8 *blk_dev_name;
240 utf8 *sz_512_n_path;
241 utf8 *logical_blk_sz_path;
242 utf8 *physical_blk_sz_path;
243
244 blk_dev_name = strrchr(blk_dev.path, '/');
245 ++blk_dev_name;
246 printf("%s:device name is %s\n", blk_dev.path, blk_dev_name);
247 sz_512_n_path = pf("/sys/block/%s/size", blk_dev_name);
248 printf("%s:reading %s\n", blk_dev.path, sz_512_n_path);
249 fd = open(sz_512_n_path, O_RDONLY);
250 if (fd == -1) {
251 dprintf(2, "%s:unable to open %s\n", blk_dev.path, sz_512_n_path);
252 exit(1);
253 }
254 free(sz_512_n_path);
255 /* reads are supposed to be atomic from sysfs... I guess */
256 r = read(fd, val_str, sizeof(val_str));
257 val_str[r - 1] = 0; /* remove the terminating '\n' */
258 blk_dev.sz_512_n = strtou64(val_str, 0, 10);
259 printf("%s:size is %"PRIu64" blocks of 512 bytes\n", blk_dev.path, blk_dev.sz_512_n);
260 close(fd);
261
262 logical_blk_sz_path = pf("/sys/block/%s/queue/logical_block_size", blk_dev_name);
263 printf("%s:reading %s\n", blk_dev.path, logical_blk_sz_path);
264 fd = open(logical_blk_sz_path, O_RDONLY);
265 if (fd == -1) {
266 dprintf(2, "%s:unable to open %s\n", blk_dev.path, logical_blk_sz_path);
267 exit(1);
268 }
269 free(logical_blk_sz_path);
270 /* reads are supposed to be atomic from sysfs... I guess */
271 r = read(fd, val_str, sizeof(val_str));
272 val_str[r - 1] = 0; /* remove the terminating '\n' */
273 blk_dev.logical_blk_sz = strtou64(val_str, 0, 10);
274 printf("%s:logical block size is %"PRIu64" bytes\n", blk_dev.path, blk_dev.logical_blk_sz);
275 close(fd);
276
277 physical_blk_sz_path = pf("/sys/block/%s/queue/physical_block_size", blk_dev_name);
278 printf("%s:reading %s\n", blk_dev.path, physical_blk_sz_path);
279 fd = open(physical_blk_sz_path, O_RDONLY);
280 if (fd == -1) {
281 dprintf(2, "%s:unable to open %s\n", blk_dev.path, physical_blk_sz_path);
282 exit(1);
283 }
284 free(physical_blk_sz_path);
285 /* reads are supposed to be atomic from sysfs... I guess */
286 r = read(fd, val_str, sizeof(val_str));
287 val_str[r - 1] = 0; /* remove the terminating '\n' */
288 blk_dev.physical_blk_sz = strtou64(val_str, 0, 10);
289 printf("%s:physical block size is %"PRIu64" bytes\n", blk_dev.path, blk_dev.physical_blk_sz);
290 close(fd);
291 }
292 static void protective_mbr_gen(void)
293 {
294 u32 *le32_whole_dev_logical_blks_n;
295 u64 whole_dev_bytes_n;
296 u64 whole_dev_logical_blks_n;
297
298 if (blk_dev.logical_blk_sz < 512) {
299 dprintf(2, "%s: something is wrong, the logical block size is %"PRIu64", below 512/0x200 bytes", blk_dev.path, blk_dev.logical_blk_sz);
300 exit(1);
301 }
302 protective_mbr = calloc(1, blk_dev.logical_blk_sz);
303
304 protective_mbr[PART_0 + 0x02] = 0x02; /* first CHS */
305 protective_mbr[PART_0 + 0x04] = 0xee; /* partition type */
306 protective_mbr[PART_0 + 0x05] = 0xff; /* last head */
307 protective_mbr[PART_0 + 0x06] = 0xff; /* last cylinder MSBs + last sector */
308 protective_mbr[PART_0 + 0x07] = 0xff; /* last cylinder LSBs */
309 protective_mbr[PART_0 + 0x08] = 0x1; /* little endian */
310
311 whole_dev_bytes_n = blk_dev.sz_512_n * 512;
312 whole_dev_logical_blks_n = whole_dev_bytes_n / blk_dev.logical_blk_sz;
313 /* cap to max, remove the MBR in LBA 0 */
314 if (whole_dev_logical_blks_n > 0x100000000)
315 whole_dev_logical_blks_n = 0xffffffff;
316 le32_whole_dev_logical_blks_n = (u32*)&protective_mbr[PART_0 + 0x0c];
317 *le32_whole_dev_logical_blks_n = htole32( /* remove mbr */
318 (u32)whole_dev_logical_blks_n - 1);
319
320 protective_mbr[BOOT_SIGNATURE_0X55] = 0x55;
321 protective_mbr[BOOT_SIGNATURE_0XAA] = 0xaa;
322 }
323 static void protective_mbr_write(void)
324 {
325 off_t r0;
326 size_t written_bytes_n;
327
328 r0 = lseek(blk_dev.fd, 0, SEEK_SET);
329 if (r0 != 0) {
330 dprintf(2, "%s:unable to reach the start of the device\n", blk_dev.path);
331 exit(1);
332 }
333 /* short writes */
334 written_bytes_n = 0;
335 loop {
336 ssize_t r1;
337
338 errno = 0;
339 r1 = write(blk_dev.fd, protective_mbr + written_bytes_n, blk_dev.logical_blk_sz - written_bytes_n);
340 if (r1 == -1) {
341 if (errno == EINTR)
342 continue;
343 dprintf(2, "%s:unable to write the protective master boot record (mbr), device mbr is now probably corrupted\n", blk_dev.path);
344 exit(1);
345 }
346 written_bytes_n += (size_t)r1;
347 if (written_bytes_n == (size_t)(blk_dev.logical_blk_sz))
348 break;
349 }
350 printf("%s:protective master boot record (mbr) written, %"PRIu64" bytes\n", blk_dev.path, blk_dev.logical_blk_sz);
351 }
352 static u8 entries_array_gen_entry(u8 entry_idx)
353 {
354 u8 *entry;
355 u64 *p64;
356
357 entry = entries_array + ENTRY_BYTES_N * entry_idx;
358 guid_write(&entry[0x00], &entries[entry_idx]->type);
359 guid_write(&entry[0x10], &entries[entry_idx]->uniq);
360 p64 = (u64*)&entry[0x20];
361 *p64 = htole64(entries[entry_idx]->first);
362 p64 = (u64*)&entry[0x28];
363 *p64 = htole64(entries[entry_idx]->last);
364 }
365 static void entries_array_gen(void)
366 {
367 u8 entry_idx;
368
369 entries_array = calloc(1, entries_lbas_n * blk_dev.logical_blk_sz);
370 entry_idx = 0;
371 loop {
372 if (entry_idx == entries_n)
373 break;
374 entries_array_gen_entry(entry_idx);
375 ++entry_idx;
376 }
377 }
378 static void hdr_primary_gen(void)
379 {
380 u64 *p64;
381 u32 *p32;
382 u16 *p16;
383 u32 le_crc32;
384
385 hdr_primary = calloc(1, blk_dev.logical_blk_sz);
386
387 memcpy(hdr_primary, hdr_signature, 8);
388
389 p32 = (u32*)&hdr_primary[0x08];
390 *p32 = htole32(HDR_REVISION);
391
392 p32 =(u32*)&hdr_primary[0x0c];
393 *p32 = htole32(HDR_BYTES_N);
394
395 /* the CRC32 will go there, 0 for its calculation */
396
397 p64 = (u64*)&hdr_primary[0x18];
398 *p64 = htole64(0x00000001); /* lba of this hdr */
399
400 p64 = (u64*)&hdr_primary[0x20];
401 *p64 = htole64(blk_dev.last_lba); /* the hdr at the end */
402
403 p64 = (u64*)&hdr_primary[0x28];
404 *p64 = htole64(hdrs.first_usable_lba);
405
406 p64 = (u64*)&hdr_primary[0x30];
407 *p64 = htole64(hdrs.last_usable_lba);
408
409 guid_write(&hdr_primary[0x38], &hdrs.disk);
410
411 p64 = (u64*)&hdr_primary[0x48];
412 *p64 = htole64(2); /* skip mbr and hdr */
413
414 p32 = (u32*)&hdr_primary[0x50];
415 *p32 = htole32((u32)(ENTRIES_ARRAY_MIN_BYTES_N/ENTRY_BYTES_N));
416
417 p32 = (u32*)&hdr_primary[0x54];
418 *p32 = htole32(ENTRY_BYTES_N);
419
420 p32 = (u32*)&hdr_primary[0x58];
421 *p32 = htole32(entries_array_crc32);
422
423 /* crc32 on exactly the header size */
424 le_crc32 = 0;
425 le_crc32_update(hdr_primary, HDR_BYTES_N, &le_crc32);
426 printf("%s:primary hdr crc32 is 0x%"PRIx32"\n", blk_dev.path, le_crc32);
427 p32 = (u32*)&hdr_primary[0x10];
428 *p32 = le_crc32;
429 }
430 static void hdr_secondary_gen(void)
431 {
432 u64 *p64;
433 u32 *p32;
434 u16 *p16;
435 u32 le_crc32;
436
437 hdr_secondary = calloc(1, blk_dev.logical_blk_sz);
438
439 memcpy(hdr_secondary, hdr_signature, 8);
440
441 p32 = (u32*)&hdr_secondary[0x08];
442 *p32 = htole32(HDR_REVISION);
443
444 p32 =(u32*)&hdr_secondary[0x0c];
445 *p32 = htole32(HDR_BYTES_N);
446
447 /* the CRC32 will go there, 0 for its calculation */
448
449 p64 = (u64*)&hdr_secondary[0x18];
450 *p64 = htole64(blk_dev.last_lba); /* this hdr */
451
452 p64 = (u64*)&hdr_secondary[0x20];
453 *p64 = htole64(1); /* the hdr at the beginning */
454
455 p64 = (u64*)&hdr_secondary[0x28];
456 *p64 = htole64(hdrs.first_usable_lba);
457
458 p64 = (u64*)&hdr_secondary[0x30];
459 *p64 = htole64(hdrs.last_usable_lba);
460
461 guid_write(&hdr_secondary[0x38], &hdrs.disk);
462
463 p64 = (u64*)&hdr_secondary[0x48];
464 *p64 = htole64(blk_dev.last_lba - entries_lbas_n);
465
466 p32 = (u32*)&hdr_secondary[0x50];
467 *p32 = htole32((u32)(ENTRIES_ARRAY_MIN_BYTES_N/ENTRY_BYTES_N));
468
469 p32 = (u32*)&hdr_secondary[0x54];
470 *p32 = htole32(ENTRY_BYTES_N);
471
472 p32 = (u32*)&hdr_secondary[0x58];
473 *p32 = htole32(entries_array_crc32);
474
475 /* crc32 on exactly the header size */
476 le_crc32 = 0;
477 le_crc32_update(hdr_secondary, HDR_BYTES_N, &le_crc32);
478 printf("%s:secondary hdr crc32 is 0x%"PRIx32"\n", blk_dev.path, le_crc32);
479 p32 = (u32*)&hdr_secondary[0x10];
480 *p32 = le_crc32;
481 }
482 static void primary_hdr_write(void)
483 {
484 off_t r0;
485 off_t start;
486 size_t written_bytes_n;
487 size_t bytes_to_write_n;
488
489 /* skip the mbr */
490 start = (off_t)blk_dev.logical_blk_sz;
491 r0 = lseek(blk_dev.fd, start, SEEK_SET);
492 if (r0 != start) {
493 dprintf(2, "%s:unable to reach the first lba of the device\n", blk_dev.path);
494 exit(1);
495 }
496 bytes_to_write_n = (size_t)(blk_dev.logical_blk_sz);
497 /* short writes */
498 written_bytes_n = 0;
499 loop {
500 ssize_t r1;
501
502 errno = 0;
503 r1 = write(blk_dev.fd, hdr_primary + written_bytes_n, bytes_to_write_n - written_bytes_n);
504 if (r1 == -1) {
505 if (errno == EINTR)
506 continue;
507 dprintf(2, "%s:unable to write the primary GPT header, block device is now probably corrupted\n", blk_dev.path);
508 exit(1);
509 }
510 written_bytes_n += (size_t)r1;
511 if (written_bytes_n == bytes_to_write_n)
512 break;
513 }
514 printf("%s:primary GPT header written, %"PRIu64" bytes\n", blk_dev.path, bytes_to_write_n);
515 }
516 static void secondary_hdr_write(void)
517 {
518 off_t r0;
519 off_t start;
520 size_t written_bytes_n;
521 size_t bytes_to_write_n;
522
523 start = (off_t)(blk_dev.last_lba * blk_dev.logical_blk_sz);
524 r0 = lseek(blk_dev.fd, start, SEEK_SET);
525 if (r0 != start) {
526 dprintf(2, "%s:unable to reach the lba of the secondary header\n", blk_dev.path);
527 exit(1);
528 }
529 bytes_to_write_n = (size_t)(blk_dev.logical_blk_sz);
530 /* short writes */
531 written_bytes_n = 0;
532 loop {
533 ssize_t r1;
534
535 errno = 0;
536 r1 = write(blk_dev.fd, hdr_secondary + written_bytes_n, bytes_to_write_n - written_bytes_n);
537 if (r1 == -1) {
538 if (errno == EINTR)
539 continue;
540 dprintf(2, "%s:unable to write the primary GPT header, block device is now probably corrupted\n", blk_dev.path);
541 exit(1);
542 }
543 written_bytes_n += (size_t)r1;
544 if (written_bytes_n == bytes_to_write_n)
545 break;
546 }
547 printf("%s:secondary GPT header written, %"PRIu64" bytes\n", blk_dev.path, bytes_to_write_n);
548 }
549 static void primary_entries_write(void)
550 {
551 off_t r0;
552 size_t written_bytes_n;
553 off_t start;
554 size_t bytes_to_write_n;
555
556 /* skip the mbr and the primary hdr */
557 start = (off_t)(blk_dev.logical_blk_sz * 2);
558 r0 = lseek(blk_dev.fd, start, SEEK_SET);
559 if (r0 != start) {
560 dprintf(2, "%s:unable to reach the first lba for the primary entries\n", blk_dev.path);
561 exit(1);
562 }
563 bytes_to_write_n = (size_t)(blk_dev.logical_blk_sz * entries_lbas_n);
564 /* short writes */
565 written_bytes_n = 0;
566 loop {
567 ssize_t r1;
568
569 errno = 0;
570 r1 = write(blk_dev.fd, entries_array + written_bytes_n, bytes_to_write_n - written_bytes_n);
571 if (r1 == -1) {
572 if (errno == EINTR)
573 continue;
574 dprintf(2, "%s:unable to write the primary entries, block device is now probably corrupted\n", blk_dev.path);
575 exit(1);
576 }
577 written_bytes_n += (size_t)r1;
578 if (written_bytes_n == bytes_to_write_n)
579 break;
580 }
581 printf("%s:primary entries written, %"PRIu64" bytes\n", blk_dev.path, bytes_to_write_n);
582 }
583 static void secondary_entries_write(void)
584 {
585 off_t r0;
586 size_t written_bytes_n;
587 off_t start;
588 size_t bytes_to_write_n;
589
590 /* skip the secondary hdr, offset arithmetic */
591 start = (off_t)(blk_dev.logical_blk_sz * (blk_dev.last_lba
592 - entries_lbas_n));
593 r0 = lseek(blk_dev.fd, start, SEEK_SET);
594 if (r0 != start) {
595 dprintf(2, "%s:unable to reach the first lba for the secondary entries\n", blk_dev.path);
596 exit(1);
597 }
598 bytes_to_write_n = (size_t)(blk_dev.logical_blk_sz * entries_lbas_n);
599 /* short writes */
600 written_bytes_n = 0;
601 loop {
602 ssize_t r1;
603
604 errno = 0;
605 r1 = write(blk_dev.fd, entries_array + written_bytes_n, bytes_to_write_n - written_bytes_n);
606 if (r1 == -1) {
607 if (errno == EINTR)
608 continue;
609 dprintf(2, "%s:unable to write the secondary entries, block device is now probably corrupted\n", blk_dev.path);
610 exit(1);
611 }
612 written_bytes_n += (size_t)r1;
613 if (written_bytes_n == bytes_to_write_n)
614 break;
615 }
616 printf("%s:secondary entries written, %"PRIu64" bytes\n", blk_dev.path, bytes_to_write_n);
617 }
618 int main(int argc, utf8 **argv)
619 {
620 u64 whole_dev_bytes_n;
621 u64 entries_bytes_n;
622
623 if (argc < 2) {
624 dprintf(2, "missing block device path\n");
625 return 1;
626 }
627 blk_dev.path = argv[1];
628 printf("block device path is %s\n", blk_dev.path);
629 blk_dev.fd = open(blk_dev.path, O_RDWR | O_SYNC);
630 if (blk_dev.fd == -1) {
631 dprintf(2, "%s:unable to open\n", blk_dev.path);
632 return 1;
633 }
634 printf("%s:opened\n", blk_dev.path);
635 sysfs_infos_get();
636
637 whole_dev_bytes_n = blk_dev.sz_512_n * 512;
638 if ((whole_dev_bytes_n % blk_dev.logical_blk_sz) != 0) {
639 dprintf(2, "%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_sz);
640 exit(1);
641 }
642 /* the total number of lba, -1 to get the offset of the last one */
643 blk_dev.last_lba = blk_dev.sz_512_n * 512 / blk_dev.logical_blk_sz - 1;
644 printf("%s:last lba is %"PRIu64"\n", blk_dev.path, blk_dev.last_lba);
645
646 entries_bytes_n = ENTRY_BYTES_N * entries_n;
647 /* we handle entries array size of ENTRIES_ARRAY_MIN_BYTES_N */
648 if (entries_bytes_n > ENTRIES_ARRAY_MIN_BYTES_N) {
649 dprintf(2, "%s:sorry,you have too many partition entries, %u, for this tool to handle\n", blk_dev.path, entries_n);
650 exit(1);
651 }
652 entries_lbas_n = ENTRIES_ARRAY_MIN_BYTES_N / blk_dev.logical_blk_sz
653 + ((ENTRIES_ARRAY_MIN_BYTES_N % blk_dev.logical_blk_sz) == 0
654 ? 0 : 1);
655 /* protective mbr, hdr, entries */
656 hdrs.first_usable_lba = 0 + 2 + entries_lbas_n;
657 /* hdr, entries */
658 hdrs.last_usable_lba = blk_dev.last_lba - 1 - entries_lbas_n;
659 printf("%s:lbas for partitions:first usable is %"PRIu64", last usable is %"PRIu64"\n", blk_dev.path, hdrs.first_usable_lba, hdrs.last_usable_lba);
660
661 entry_root.last = hdrs.last_usable_lba;
662
663 entries_array_gen();
664
665 le_crc32_tbl_gen();
666 /* crc32 on exactly the entries array size, not lba bounded */
667 entries_array_crc32 = 0;
668 le_crc32_update(entries_array, (ENTRIES_ARRAY_MIN_BYTES_N/ENTRY_BYTES_N)
669 * ENTRY_BYTES_N, &entries_array_crc32);
670 printf("%s:entries array crc32 is 0x%"PRIx32"\n", blk_dev.path, entries_array_crc32);
671 hdr_primary_gen();
672 hdr_secondary_gen();
673 protective_mbr_gen();
674
675 protective_mbr_write();
676 primary_hdr_write();
677 secondary_hdr_write();
678 primary_entries_write();
679 secondary_entries_write();
680 return 0;
681 }
682 #endif
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/sylware/nyanlinux

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/sylware/nyanlinux

Clone this repository using git:
git clone git://git.rocketgit.com/user/sylware/nyanlinux

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main