sylware / nyanlinux (public) (License: AFFERO GPLv3) (since 2019-09-09) (hash sha1)
scripts for a lean, from scratch, amd hardware, linux distro

/files/nyangpt.c (dc5dcbd940c45f5f636506f5272c54318879b7d2) (19181 bytes) (mode 100644) (type blob)

#ifndef NYANGPT_C
#define NYANGPT_C
/*
 * Copyright 2021 Sylvain BERTRAND <sylvain.bertrand@legeek.net>
 * LICENSE: GNU AFFERO GPLV3 
 */
/*
 * quick and dirty, ultra minimal, source oriented, UEFI GPT partition creator
 */
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdint.h>
#include <inttypes.h>
#include <endian.h>
#include <errno.h>
/*
 * how to get pertinent device information from sysfs for GPT partitioning
 *
 * for a /dev/sdX block device:
 * /sys/block/sdX/size = size of the device in blocks of 512 bytes (hardcoded)
 * /sys/block/sdX/queue/logical_block_size = size in bytes of a logical block
 *     which is the size used by LBA (Logical Block Access) offsets used
 *     in GPT partitions
 * /sys/block/sdX/queue/physical_block_size = size in bytes of a physical block
 */
#define utf8 uint8_t
#define X64_UTF8_BYTES_MAX (sizeof("18446744073709551615") - 1)
/* meh */
#define strtou64 strtoul
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t
#define s32 int32_t
#define u64 uint64_t
#define loop for(;;)
/******************************************************************************/
/* stolen and cosmetized, not validated on big endian */
/* http://home.thep.lu.se/~bjorn/crc/ */
static u32 le_crc32_for_byte(u32 r)
{
	u8 j;

	j = 0;
	loop  {
		if (j == 8)
			break;
		r = (r & 1 ? 0 : (u32)0xedb88320) ^ r >> 1;
		++j;
	}
	return r ^ (u32)0xff000000;
}
static u32 le_crc32_tbl[0x100];
static void le_crc32_tbl_gen(void)
{
	u32 i;

	i = 0;
	loop {
		if (i == 0x100)
			break;
		le_crc32_tbl[i] = le_crc32_for_byte(i);
		++i;
	}
}
static void le_crc32_update(void *data, u64 bytes_n, u32* crc)
{
	u64 i;

	i = 0;
	loop {
		if (i == bytes_n)
			break;
		*crc = le_crc32_tbl[(u8)*crc ^ ((u8*)data)[i]] ^ *crc >> 8;
		++i;
	}
}
/******************************************************************************/
/*----------------------------------------------------------------------------*/
static struct {
	utf8 *path;
	u64 sz_512_n;
	u64 logical_blk_sz;
	u64 physical_blk_sz;
	int fd;
	u64 last_lba;
} blk_dev;
/*----------------------------------------------------------------------------*/
static u8 *protective_mbr;
/* offsets */
#define BOOT_SIGNATURE_0X55	0x1fe
#define BOOT_SIGNATURE_0XAA	0x1ff
#define PART_0			0x1be
/*----------------------------------------------------------------------------*/
struct guid_t {
	u32 blk_0;
	u16 blk_1;
	u16 blk_2;
	u16 blk_3;
	u8 blk_4[6];
};
#define BLK_0 0x0
#define BLK_1 0x4
#define BLK_2 0x6
#define BLK_3 0x8
#define BLK_4 0xa
struct entry_t {
	struct guid_t type;
	struct guid_t uniq;
	u64 first;
	u64 last;
	u64 attrs;
	/* utf-16 names? really?... */
};
#define ENTRIES_ARRAY_MIN_BYTES_N 16384 /* specs: minimum to book on the disk */
#define ENTRY_BYTES_N 0x80
/* make it at least 128MB */
static struct entry_t entry_efi_system =
{
	.type.blk_0 = 0xc12a7328,
	.type.blk_1 = 0xf81f,
	.type.blk_2 = 0x11d2,
	.type.blk_3 = 0xba4b,
	.type.blk_4 = {0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b},

	.uniq.blk_0 = 0xdeadbeef,
	.uniq.blk_1 = 0x0000,
	.uniq.blk_2 = 0x0000,
	.uniq.blk_3 = 0x0000,
	.uniq.blk_4 = {0x00, 0x0, 0x00, 0x00, 0x00, 0x01},

	.first = 0x0000000000000022,
	.last  = 0x000000000004ffff,

	.attrs = 0,
};
static struct entry_t entry_root =
{
	/* linux root x86_64 GUID */
	.type.blk_0 = 0x4f68bce3,
	.type.blk_1 = 0xe8cd,
	.type.blk_2 = 0x4db1,
	.type.blk_3 = 0x96e7,
	.type.blk_4 = {0xfb, 0xca, 0xf9, 0x84, 0xb7, 0x09},

	.uniq.blk_0 = 0xdeadbeef,
	.uniq.blk_1 = 0x0000,
	.uniq.blk_2 = 0x0000,
	.uniq.blk_3 = 0x0000,
	.uniq.blk_4 = {0x00, 0x0, 0x00, 0x00, 0x00, 0x02},

	/* everything else */
	.first = 0x0000000000050000,
	.last  = 0x0, /* generated later */

	.attrs = 0,
};
static struct entry_t *entries[2] = {
	&entry_efi_system,
	&entry_root,
};
static u8 entries_n = 2;
static u8 entries_lbas_n;
static u8 *entries_array;
static u32 entries_array_crc32;
/*----------------------------------------------------------------------------*/
struct hdrs_t { /* there are 2 headers, each must fit in a logical block */
	u64 first_usable_lba;
	u64 last_usable_lba;
	struct guid_t disk;
};
static struct hdrs_t hdrs = {
	.disk.blk_0 = 0xdeadbeef,
	.disk.blk_1 = 0x0000,
	.disk.blk_2 = 0x0000,
	.disk.blk_3 = 0x0000,
	.disk.blk_4 = {0x00, 0x0, 0x00, 0x00, 0x00, 0x00},
};
static u8 hdr_signature[8] = "EFI PART";
#define HDR_REVISION 0x00010000 /* 1.0 */
#define HDR_BYTES_N 0x5c /* 92 bytes */
static u8 *hdr_primary;
static u8 *hdr_secondary;
/*----------------------------------------------------------------------------*/
static utf8 *pf(utf8 *fmt,...)
{
	va_list ap;
	int r;
	utf8 *r_str;

	va_start(ap, fmt);
	r = vsnprintf(0, 0, fmt, ap);
	va_end(ap);

	r_str = malloc(r + 1); /* we want a terminating 0 */

	va_start(ap, fmt);
	vsnprintf(r_str, r + 1, fmt, ap); /* has room for the terminating 0 */
	va_end(ap);
	return r_str;
}
/* brain damaged mixed-endian guid */
static void guid_write(void *dest, struct guid_t *src)
{
	u8 *d;
	u32 *p32;
	u16 *p16;

	d = (u8*)dest;

	p32 = (u32*)d;
	*p32 = htole32(src->blk_0); /* little endian */
	d += 4;
	p16 = (u16*)d;
	*p16 = htole16(src->blk_1); /* little endian */
	d += 2;
	p16 = (u16*)d;
	*p16 = htole16(src->blk_2); /* little endian */
	d += 2;
	p16 = (u16*)d;
	*p16 = htobe16(src->blk_3); /* big endian */
	d += 2;
	d[0] = src->blk_4[0];
	d[1] = src->blk_4[1];
	d[2] = src->blk_4[2];
	d[3] = src->blk_4[3];
	d[4] = src->blk_4[4];
	d[5] = src->blk_4[5];
}
static void sysfs_infos_get(void)
{
	int fd;
	int r;
	utf8 val_str[X64_UTF8_BYTES_MAX + 1]; /* 0 terminating char */
	utf8 *blk_dev_name;
	utf8 *sz_512_n_path;
	utf8 *logical_blk_sz_path;
	utf8 *physical_blk_sz_path;

	blk_dev_name = strrchr(blk_dev.path, '/');
	++blk_dev_name;
	printf("%s:device name is %s\n", blk_dev.path, blk_dev_name);
	sz_512_n_path = pf("/sys/block/%s/size", blk_dev_name);
	printf("%s:reading %s\n", blk_dev.path, sz_512_n_path);
	fd = open(sz_512_n_path, O_RDONLY);
	if (fd == -1) {
		dprintf(2, "%s:unable to open %s\n", blk_dev.path, sz_512_n_path);
		exit(1);
	}
	free(sz_512_n_path);
	/* reads are supposed to be atomic from sysfs... I guess */
	r = read(fd, val_str, sizeof(val_str));
	val_str[r - 1] = 0; /* remove the terminating '\n' */
	blk_dev.sz_512_n = strtou64(val_str, 0, 10);	
	printf("%s:size is %"PRIu64" blocks of 512 bytes\n", blk_dev.path, blk_dev.sz_512_n);
	close(fd);

	logical_blk_sz_path = pf("/sys/block/%s/queue/logical_block_size", blk_dev_name);
	printf("%s:reading %s\n", blk_dev.path, logical_blk_sz_path);
	fd = open(logical_blk_sz_path, O_RDONLY);
	if (fd == -1) {
		dprintf(2, "%s:unable to open %s\n", blk_dev.path, logical_blk_sz_path);
		exit(1);
	}
	free(logical_blk_sz_path);
	/* reads are supposed to be atomic from sysfs... I guess */
	r = read(fd, val_str, sizeof(val_str));
	val_str[r - 1] = 0; /* remove the terminating '\n' */
	blk_dev.logical_blk_sz = strtou64(val_str, 0, 10);	
	printf("%s:logical block size is %"PRIu64" bytes\n", blk_dev.path, blk_dev.logical_blk_sz);
	close(fd);

	physical_blk_sz_path = pf("/sys/block/%s/queue/physical_block_size", blk_dev_name);
	printf("%s:reading %s\n", blk_dev.path, physical_blk_sz_path);
	fd = open(physical_blk_sz_path, O_RDONLY);
	if (fd == -1) {
		dprintf(2, "%s:unable to open %s\n", blk_dev.path, physical_blk_sz_path);
		exit(1);
	}
	free(physical_blk_sz_path);
	/* reads are supposed to be atomic from sysfs... I guess */
	r = read(fd, val_str, sizeof(val_str));
	val_str[r - 1] = 0; /* remove the terminating '\n' */
	blk_dev.physical_blk_sz = strtou64(val_str, 0, 10);	
	printf("%s:physical block size is %"PRIu64" bytes\n", blk_dev.path, blk_dev.physical_blk_sz);
	close(fd);
}
static void protective_mbr_gen(void)
{
	u32 *le32_whole_dev_logical_blks_n;
	u64 whole_dev_bytes_n;
	u64 whole_dev_logical_blks_n;

	if (blk_dev.logical_blk_sz < 512) {
		dprintf(2, "%s: something is wrong, the logical block size is %"PRIu64", below 512/0x200 bytes", blk_dev.path, blk_dev.logical_blk_sz);
		exit(1);
	}
	protective_mbr = calloc(1, blk_dev.logical_blk_sz);

	protective_mbr[PART_0 + 0x02] = 0x02; /* first CHS */
	protective_mbr[PART_0 + 0x04] = 0xee; /* partition type */
	protective_mbr[PART_0 + 0x05] = 0xff; /* last head */
	protective_mbr[PART_0 + 0x06] = 0xff; /* last cylinder MSBs + last sector */
	protective_mbr[PART_0 + 0x07] = 0xff; /* last cylinder LSBs */
	protective_mbr[PART_0 + 0x08] = 0x1; /* little endian */

	whole_dev_bytes_n = blk_dev.sz_512_n * 512;
	whole_dev_logical_blks_n = whole_dev_bytes_n / blk_dev.logical_blk_sz;
	/* cap to max, remove the MBR in LBA 0 */
	if (whole_dev_logical_blks_n > 0x100000000)
		whole_dev_logical_blks_n = 0xffffffff;
	le32_whole_dev_logical_blks_n = (u32*)&protective_mbr[PART_0 + 0x0c];
	*le32_whole_dev_logical_blks_n = htole32( /* remove mbr */
					(u32)whole_dev_logical_blks_n - 1);

	protective_mbr[BOOT_SIGNATURE_0X55] = 0x55;
	protective_mbr[BOOT_SIGNATURE_0XAA] = 0xaa;
}
static void protective_mbr_write(void)
{
	off_t r0;
	size_t written_bytes_n;

	r0 = lseek(blk_dev.fd, 0, SEEK_SET);
	if (r0 != 0) {
		dprintf(2, "%s:unable to reach the start of the device\n", blk_dev.path);
		exit(1);
	}
	/* short writes */
	written_bytes_n = 0;
	loop {
		ssize_t r1;

		errno = 0;
		r1 = write(blk_dev.fd, protective_mbr + written_bytes_n, blk_dev.logical_blk_sz - written_bytes_n);
		if (r1 == -1) {
			if (errno == EINTR)
				continue;
			dprintf(2, "%s:unable to write the protective master boot record (mbr), device mbr is now probably corrupted\n", blk_dev.path);
			exit(1);
		}
		written_bytes_n += (size_t)r1;
		if (written_bytes_n == (size_t)(blk_dev.logical_blk_sz))
			break;
	}
	printf("%s:protective master boot record (mbr) written, %"PRIu64" bytes\n", blk_dev.path, blk_dev.logical_blk_sz);
}
static u8 entries_array_gen_entry(u8 entry_idx)
{
	u8 *entry;
	u64 *p64;

	entry = entries_array + ENTRY_BYTES_N * entry_idx;
	guid_write(&entry[0x00], &entries[entry_idx]->type);
	guid_write(&entry[0x10], &entries[entry_idx]->uniq);
	p64 = (u64*)&entry[0x20];
	*p64 = htole64(entries[entry_idx]->first);
	p64 = (u64*)&entry[0x28];
	*p64 = htole64(entries[entry_idx]->last);
}
static void entries_array_gen(void)
{
	u8 entry_idx;

	entries_array = calloc(1, entries_lbas_n * blk_dev.logical_blk_sz);
	entry_idx = 0;
	loop {
		if (entry_idx == entries_n)
			break;
		entries_array_gen_entry(entry_idx);
		++entry_idx;
	}
}
static void hdr_primary_gen(void)
{
	u64 *p64;
	u32 *p32;
	u16 *p16;
	u32 le_crc32;

	hdr_primary = calloc(1, blk_dev.logical_blk_sz);

	memcpy(hdr_primary, hdr_signature, 8);

	p32 = (u32*)&hdr_primary[0x08];
	*p32 = htole32(HDR_REVISION);

	p32 =(u32*)&hdr_primary[0x0c];
	*p32 = htole32(HDR_BYTES_N);

	/* the CRC32 will go there, 0 for its calculation */

	p64 = (u64*)&hdr_primary[0x18];
	*p64 = htole64(0x00000001); /* lba of this hdr */

	p64 = (u64*)&hdr_primary[0x20];
	*p64 = htole64(blk_dev.last_lba); /* the hdr at the end */

	p64 = (u64*)&hdr_primary[0x28];
	*p64 = htole64(hdrs.first_usable_lba);

	p64 = (u64*)&hdr_primary[0x30];
	*p64 = htole64(hdrs.last_usable_lba);

	guid_write(&hdr_primary[0x38], &hdrs.disk);

	p64 = (u64*)&hdr_primary[0x48];
	*p64 = htole64(2); /* skip mbr and hdr */

	p32 = (u32*)&hdr_primary[0x50];
	*p32 = htole32((u32)(ENTRIES_ARRAY_MIN_BYTES_N/ENTRY_BYTES_N));

	p32 = (u32*)&hdr_primary[0x54];
	*p32 = htole32(ENTRY_BYTES_N);

	p32 = (u32*)&hdr_primary[0x58];
	*p32 = htole32(entries_array_crc32);

	/* crc32 on exactly the header size */
	le_crc32 = 0;
	le_crc32_update(hdr_primary, HDR_BYTES_N, &le_crc32);
	printf("%s:primary hdr crc32 is 0x%"PRIx32"\n", blk_dev.path, le_crc32);
	p32 = (u32*)&hdr_primary[0x10];
	*p32 = le_crc32;
}
static void hdr_secondary_gen(void)
{
	u64 *p64;
	u32 *p32;
	u16 *p16;
	u32 le_crc32;

	hdr_secondary = calloc(1, blk_dev.logical_blk_sz);

	memcpy(hdr_secondary, hdr_signature, 8);

	p32 = (u32*)&hdr_secondary[0x08];
	*p32 = htole32(HDR_REVISION);

	p32 =(u32*)&hdr_secondary[0x0c];
	*p32 = htole32(HDR_BYTES_N);

	/* the CRC32 will go there, 0 for its calculation */

	p64 = (u64*)&hdr_secondary[0x18];
	*p64 = htole64(blk_dev.last_lba); /* this hdr */

	p64 = (u64*)&hdr_secondary[0x20];
	*p64 = htole64(1); /* the hdr at the beginning */

	p64 = (u64*)&hdr_secondary[0x28];
	*p64 = htole64(hdrs.first_usable_lba);

	p64 = (u64*)&hdr_secondary[0x30];
	*p64 = htole64(hdrs.last_usable_lba);

	guid_write(&hdr_secondary[0x38], &hdrs.disk);

	p64 = (u64*)&hdr_secondary[0x48];
	*p64 = htole64(blk_dev.last_lba - entries_lbas_n);

	p32 = (u32*)&hdr_secondary[0x50];
	*p32 = htole32((u32)(ENTRIES_ARRAY_MIN_BYTES_N/ENTRY_BYTES_N));

	p32 = (u32*)&hdr_secondary[0x54];
	*p32 = htole32(ENTRY_BYTES_N); 

	p32 = (u32*)&hdr_secondary[0x58];
	*p32 = htole32(entries_array_crc32);

	/* crc32 on exactly the header size */
	le_crc32 = 0;
	le_crc32_update(hdr_secondary, HDR_BYTES_N, &le_crc32);
	printf("%s:secondary hdr crc32 is 0x%"PRIx32"\n", blk_dev.path, le_crc32);
	p32 = (u32*)&hdr_secondary[0x10];
	*p32 = le_crc32;
}
static void primary_hdr_write(void)
{
	off_t r0;
	off_t start;
	size_t written_bytes_n;
	size_t bytes_to_write_n;

	/* skip the mbr */
	start = (off_t)blk_dev.logical_blk_sz;
	r0 = lseek(blk_dev.fd, start, SEEK_SET);
	if (r0 != start) {
		dprintf(2, "%s:unable to reach the first lba of the device\n", blk_dev.path);
		exit(1);
	}
	bytes_to_write_n = (size_t)(blk_dev.logical_blk_sz);
	/* short writes */
	written_bytes_n = 0;
	loop {
		ssize_t r1;

		errno = 0;
		r1 = write(blk_dev.fd, hdr_primary + written_bytes_n, bytes_to_write_n - written_bytes_n);
		if (r1 == -1) {
			if (errno == EINTR)
				continue;
			dprintf(2, "%s:unable to write the primary GPT header, block device is now probably corrupted\n", blk_dev.path);
			exit(1);
		}
		written_bytes_n += (size_t)r1;
		if (written_bytes_n == bytes_to_write_n)
			break;
	}
	printf("%s:primary GPT header written, %"PRIu64" bytes\n", blk_dev.path, bytes_to_write_n);
}
static void secondary_hdr_write(void)
{
	off_t r0;
	off_t start;
	size_t written_bytes_n;
	size_t bytes_to_write_n;

	start = (off_t)(blk_dev.last_lba * blk_dev.logical_blk_sz);
	r0 = lseek(blk_dev.fd, start, SEEK_SET);
	if (r0 != start) {
		dprintf(2, "%s:unable to reach the lba of the secondary header\n", blk_dev.path);
		exit(1);
	}
	bytes_to_write_n = (size_t)(blk_dev.logical_blk_sz);
	/* short writes */
	written_bytes_n = 0;
	loop {
		ssize_t r1;

		errno = 0;
		r1 = write(blk_dev.fd, hdr_secondary + written_bytes_n, bytes_to_write_n - written_bytes_n);
		if (r1 == -1) {
			if (errno == EINTR)
				continue;
			dprintf(2, "%s:unable to write the primary GPT header, block device is now probably corrupted\n", blk_dev.path);
			exit(1);
		}
		written_bytes_n += (size_t)r1;
		if (written_bytes_n == bytes_to_write_n)
			break;
	}
	printf("%s:secondary GPT header written, %"PRIu64" bytes\n", blk_dev.path, bytes_to_write_n);
}
static void primary_entries_write(void)
{
	off_t r0;
	size_t written_bytes_n;
	off_t start;
	size_t bytes_to_write_n;

	/* skip the mbr and the primary hdr */
	start = (off_t)(blk_dev.logical_blk_sz * 2);
	r0 = lseek(blk_dev.fd, start, SEEK_SET);
	if (r0 != start) {
		dprintf(2, "%s:unable to reach the first lba for the primary entries\n", blk_dev.path);
		exit(1);
	}
	bytes_to_write_n = (size_t)(blk_dev.logical_blk_sz * entries_lbas_n);
	/* short writes */
	written_bytes_n = 0;
	loop {
		ssize_t r1;

		errno = 0;
		r1 = write(blk_dev.fd, entries_array + written_bytes_n, bytes_to_write_n - written_bytes_n);
		if (r1 == -1) {
			if (errno == EINTR)
				continue;
			dprintf(2, "%s:unable to write the primary entries, block device is now probably corrupted\n", blk_dev.path);
			exit(1);
		}
		written_bytes_n += (size_t)r1;
		if (written_bytes_n == bytes_to_write_n)
			break;
	}
	printf("%s:primary entries written, %"PRIu64" bytes\n", blk_dev.path, bytes_to_write_n);
}
static void secondary_entries_write(void)
{
	off_t r0;
	size_t written_bytes_n;
	off_t start;
	size_t bytes_to_write_n;

	/* skip the secondary hdr, offset arithmetic */
	start = (off_t)(blk_dev.logical_blk_sz * (blk_dev.last_lba
							- entries_lbas_n));
	r0 = lseek(blk_dev.fd, start, SEEK_SET);
	if (r0 != start) {
		dprintf(2, "%s:unable to reach the first lba for the secondary entries\n", blk_dev.path);
		exit(1);
	}
	bytes_to_write_n = (size_t)(blk_dev.logical_blk_sz * entries_lbas_n);
	/* short writes */
	written_bytes_n = 0;
	loop {
		ssize_t r1;

		errno = 0;
		r1 = write(blk_dev.fd, entries_array + written_bytes_n, bytes_to_write_n - written_bytes_n);
		if (r1 == -1) {
			if (errno == EINTR)
				continue;
			dprintf(2, "%s:unable to write the secondary entries, block device is now probably corrupted\n", blk_dev.path);
			exit(1);
		}
		written_bytes_n += (size_t)r1;
		if (written_bytes_n == bytes_to_write_n)
			break;
	}
	printf("%s:secondary entries written, %"PRIu64" bytes\n", blk_dev.path, bytes_to_write_n);
}
int main(int argc, utf8 **argv)
{
	u64 whole_dev_bytes_n;
	u64 entries_bytes_n;

	if (argc < 2) {
		dprintf(2, "missing block device path\n");
		return 1;	
	}
	blk_dev.path = argv[1];
	printf("block device path is %s\n", blk_dev.path);
	blk_dev.fd = open(blk_dev.path, O_RDWR | O_SYNC);
	if (blk_dev.fd == -1) {
		dprintf(2, "%s:unable to open\n", blk_dev.path);
		return 1;
	}
	printf("%s:opened\n", blk_dev.path);
	sysfs_infos_get();

	whole_dev_bytes_n = blk_dev.sz_512_n * 512;
	if ((whole_dev_bytes_n % blk_dev.logical_blk_sz) != 0) {
		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);
		exit(1);
	}
	/* the total number of lba, -1 to get the offset of the last one */
	blk_dev.last_lba = blk_dev.sz_512_n * 512 / blk_dev.logical_blk_sz - 1;
	printf("%s:last lba is %"PRIu64"\n", blk_dev.path, blk_dev.last_lba);

	entries_bytes_n = ENTRY_BYTES_N * entries_n;
	/* we handle entries array size of ENTRIES_ARRAY_MIN_BYTES_N */
	if (entries_bytes_n > ENTRIES_ARRAY_MIN_BYTES_N) {
		dprintf(2, "%s:sorry,you have too many partition entries, %u, for this tool to handle\n", blk_dev.path, entries_n);
		exit(1);
	}
	entries_lbas_n = ENTRIES_ARRAY_MIN_BYTES_N / blk_dev.logical_blk_sz
		+ ((ENTRIES_ARRAY_MIN_BYTES_N % blk_dev.logical_blk_sz) == 0
								? 0 : 1);
	/* protective mbr, hdr, entries */
	hdrs.first_usable_lba = 0 + 2 + entries_lbas_n;
	/* hdr, entries */
	hdrs.last_usable_lba = blk_dev.last_lba - 1 - entries_lbas_n;
	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);

	entry_root.last = hdrs.last_usable_lba;

	entries_array_gen();		

	le_crc32_tbl_gen();
	/* crc32 on exactly the entries array size, not lba bounded */
	entries_array_crc32 = 0;
	le_crc32_update(entries_array, (ENTRIES_ARRAY_MIN_BYTES_N/ENTRY_BYTES_N)
					* ENTRY_BYTES_N, &entries_array_crc32);
	printf("%s:entries array crc32 is 0x%"PRIx32"\n", blk_dev.path, entries_array_crc32);
	hdr_primary_gen();
	hdr_secondary_gen();
	protective_mbr_gen();

	protective_mbr_write();
	primary_hdr_write();
	secondary_hdr_write();
	primary_entries_write();
	secondary_entries_write();
	return 0;
}
#endif


Mode Type Size Ref File
100644 blob 5 8eba6c8dd4dcaf6166bd22285ed34625f38a84ff .gitignore
100755 blob 1587 57fa4264b9ee0ae0a6f678f2527a05d3b22dda78 00-bootstrap-build.sh
100755 blob 848 a30f443bf405d56682efe3b4c5d3a19d5f7eb45d 01-re-bootstrap-build.sh
100644 blob 2142 f19c2d6b293244bb11a3f74ee77c10675cadc7d6 INSTALL
100644 blob 30 c9b735fa1332286f4b3f5f81fa10527fd7506b6e LICENSE
040000 tree - b0cd282b9b3327426674a7ae7d3f2bf20717d404 builders
100644 blob 1773 ef1551089a803bde37e36edc8d61bb819d06f793 conf.bootstrap.sh
100644 blob 479 8cc15efe46965ac7750fe304460f5a2b0aa4201c conf.sh
040000 tree - 7736496abef80608f40188d3f4425ef67a16375e files
100755 blob 356 8fb8be28ac72f7214b59934b9f74a682665f2d32 pkg-build
100644 blob 22800641 e9e6291054c857401f6835c728f31541dae4311e steam.tar.bz2
100644 blob 173 2047af328b22f9d146585cd9e759edbc18122250 utils.sh
040000 tree - 8e23f551092a35f82b37129dd08c35c4d313c17b x64
040000 tree - b7a22de7f5cbd97650dd45412ef7d4246e395eb8 x86
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