Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bb9fcb1e authored by Elliott Hughes's avatar Elliott Hughes Committed by Gerrit Code Review
Browse files

Merge "Remove gpttool."

parents fe39394e 6454a043
Loading
Loading
Loading
Loading

gpttool/Android.mk

deleted100644 → 0
+0 −14
Original line number Diff line number Diff line
ifeq ($(HOST_OS),linux)

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := gpttool.c
LOCAL_STATIC_LIBRARIES := libz
LOCAL_CFLAGS := -Werror

LOCAL_MODULE := gpttool

include $(BUILD_HOST_EXECUTABLE)

endif

gpttool/gpttool.c

deleted100644 → 0
+0 −373
Original line number Diff line number Diff line
/*
** Copyright 2011, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>

#include <zlib.h>

#include <linux/fs.h>

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;

const u8 partition_type_uuid[16] = {
	0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
	0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7,
};


#define EFI_VERSION 0x00010000
#define EFI_MAGIC "EFI PART"
#define EFI_ENTRIES 128
#define EFI_NAMELEN 36

struct efi_header {
	u8 magic[8];

	u32 version;
	u32 header_sz;

	u32 crc32;
	u32 reserved;

	u64 header_lba;
	u64 backup_lba;
	u64 first_lba;
	u64 last_lba;

	u8 volume_uuid[16];

	u64 entries_lba;

	u32 entries_count;
	u32 entries_size;
	u32 entries_crc32;
} __attribute__((packed));

struct efi_entry {
	u8 type_uuid[16];
	u8 uniq_uuid[16];
	u64 first_lba;
	u64 last_lba;
	u64 attr;
	u16 name[EFI_NAMELEN];
};

struct ptable {
	u8 mbr[512];
	union {
		struct efi_header header;
		u8 block[512];
	};
	struct efi_entry entry[EFI_ENTRIES];	
};

void get_uuid(u8 *uuid)
{
	int fd;
	fd = open("/dev/urandom", O_RDONLY);
	read(fd, uuid, 16);
	close(fd);
}

void init_mbr(u8 *mbr, u32 blocks)
{
	mbr[0x1be] = 0x00; // nonbootable
	mbr[0x1bf] = 0xFF; // bogus CHS
	mbr[0x1c0] = 0xFF;
	mbr[0x1c1] = 0xFF;

	mbr[0x1c2] = 0xEE; // GPT partition
	mbr[0x1c3] = 0xFF; // bogus CHS
	mbr[0x1c4] = 0xFF;
	mbr[0x1c5] = 0xFF;

	mbr[0x1c6] = 0x01; // start
	mbr[0x1c7] = 0x00;
	mbr[0x1c8] = 0x00;
	mbr[0x1c9] = 0x00;

	memcpy(mbr + 0x1ca, &blocks, sizeof(u32));

	mbr[0x1fe] = 0x55;
	mbr[0x1ff] = 0xaa;
}

int add_ptn(struct ptable *ptbl, u64 first, u64 last, const char *name)
{
	struct efi_header *hdr = &ptbl->header;
	struct efi_entry *entry = ptbl->entry;
	unsigned n;

	if (first < 34) {
		fprintf(stderr,"partition '%s' overlaps partition table\n", name);
		return -1;
	}

	if (last > hdr->last_lba) {
		fprintf(stderr,"partition '%s' does not fit on disk\n", name);
		return -1;
	}
	for (n = 0; n < EFI_ENTRIES; n++, entry++) {
		if (entry->type_uuid[0])
			continue;
		memcpy(entry->type_uuid, partition_type_uuid, 16);
		get_uuid(entry->uniq_uuid);
		entry->first_lba = first;
		entry->last_lba = last;
		for (n = 0; (n < EFI_NAMELEN) && *name; n++)
			entry->name[n] = *name++;
		return 0;
	}
	fprintf(stderr,"out of partition table entries\n");
	return -1;
}

int usage(void)
{
	fprintf(stderr,
		"usage: gpttool write <disk> [ <partition> ]*\n"
		"       gpttool read <disk>\n"
		"       gpttool test [ <partition> ]*\n"
		"\n"
		"partition:  [<name>]:<size>[kmg] | @<file-of-partitions>\n"
		);
	return 0;
}

void show(struct ptable *ptbl)
{
	struct efi_entry *entry = ptbl->entry;
	unsigned n, m;
	char name[EFI_NAMELEN + 1];

	fprintf(stderr,"ptn  start block   end block     name\n");
	fprintf(stderr,"---- ------------- ------------- --------------------\n");

	for (n = 0; n < EFI_ENTRIES; n++, entry++) {
		if (entry->type_uuid[0] == 0)
			break;
		for (m = 0; m < EFI_NAMELEN; m++) {
			name[m] = entry->name[m] & 127;
		}
		name[m] = 0;
		fprintf(stderr,"#%03d %13lld %13lld %s\n",
			n + 1, entry->first_lba, entry->last_lba, name);
	}
}

u64 find_next_lba(struct ptable *ptbl)
{
	struct efi_entry *entry = ptbl->entry;
	unsigned n;
	u64 a = 0;
	for (n = 0; n < EFI_ENTRIES; n++, entry++) {
		if ((entry->last_lba + 1) > a)
			a = entry->last_lba + 1;
	}
	return a;
}

u64 next_lba = 0;

u64 parse_size(char *sz)
{
	int l = strlen(sz);
	u64 n = strtoull(sz, 0, 10);
	if (l) {
		switch(sz[l-1]){
		case 'k':
		case 'K':
			n *= 1024;
			break;
		case 'm':
		case 'M':
			n *= (1024 * 1024);
			break;
		case 'g':
		case 'G':
			n *= (1024 * 1024 * 1024);
			break;
		}
	}
	return n;
}

int parse_ptn(struct ptable *ptbl, char *x)
{
	char *y = strchr(x, ':');
	u64 sz;

	if (!y) {
		fprintf(stderr,"invalid partition entry: %s\n", x);
		return -1;
	}
	*y++ = 0;

	if (*y == 0) {
		sz = ptbl->header.last_lba - next_lba;
	} else {
		sz = parse_size(y);
		if (sz & 511) {
			fprintf(stderr,"partition size must be multiple of 512\n");
			return -1;
		}
		sz /= 512;
	}

	if (sz == 0) {
		fprintf(stderr,"zero size partitions not allowed\n");
		return -1;
	}

	if (x[0] && add_ptn(ptbl, next_lba, next_lba + sz - 1, x))
		return -1;

	next_lba = next_lba + sz;
	return 0;
}

int main(int argc, char **argv)
{
	struct ptable ptbl;
	struct efi_header *hdr = &ptbl.header;
	u32 n;
	u64 sz;
	int fd;
	const char *device;
	int real_disk = 0;

	if (argc < 2)
		return usage();

	if (!strcmp(argv[1], "write")) {
		if (argc < 3)
			return usage();
		device = argv[2];
		argc -= 2;
		argv += 2;
		real_disk = 1;
	} else if (!strcmp(argv[1], "test")) {
		argc -= 1;
		argv += 1;
		real_disk = 0;
		sz = 2097152 * 16;
		fprintf(stderr,"< simulating 16GB disk >\n\n");
	} else {
		return usage();
	}

	if (real_disk) {
		if (!strcmp(device, "/dev/sda") || 
		    !strcmp(device, "/dev/sdb")) {
			fprintf(stderr,"error: refusing to partition sda or sdb\n");
			return -1;
		}
		
		fd = open(device, O_RDWR);
		if (fd < 0) {
			fprintf(stderr,"error: cannot open '%s'\n", device);
			return -1;
		}
		if (ioctl(fd, BLKGETSIZE64, &sz)) {
			fprintf(stderr,"error: cannot query block device size\n");
			return -1;
		}
		sz /= 512;
		fprintf(stderr,"blocks %lld\n", sz);
	}

	memset(&ptbl, 0, sizeof(ptbl));

	init_mbr(ptbl.mbr, sz - 1);

	memcpy(hdr->magic, EFI_MAGIC, sizeof(hdr->magic));
	hdr->version = EFI_VERSION;
	hdr->header_sz = sizeof(struct efi_header);
	hdr->header_lba = 1;
	hdr->backup_lba = sz - 1;
	hdr->first_lba = 34;
	hdr->last_lba = sz - 1;
	get_uuid(hdr->volume_uuid);
	hdr->entries_lba = 2;
	hdr->entries_count = 128;
	hdr->entries_size = sizeof(struct efi_entry);

	while (argc > 1) {
		if (argv[1][0] == '@') {
			char line[256], *p;
			FILE *f;
			f = fopen(argv[1] + 1, "r");
			if (!f) {
				fprintf(stderr,"cannot read partitions from '%s\n", argv[1]);
				return -1;
			}
			while (fgets(line, sizeof(line), f)) {
				p = line + strlen(line);
				while (p > line) {
					p--;
					if (*p > ' ')
						break;
					*p = 0;
				}
				p = line;
				while (*p && (*p <= ' '))
					p++;
				if (*p == '#')
					continue;
				if (*p == 0)
					continue;
				if (parse_ptn(&ptbl, p))
					return -1;
			}
			fclose(f);
		} else {	
			if (parse_ptn(&ptbl, argv[1]))
				return -1;
		}
		argc--;
		argv++;
	}

	n = crc32(0, Z_NULL, 0);
	n = crc32(n, (void*) ptbl.entry, sizeof(ptbl.entry));
	hdr->entries_crc32 = n;

	n = crc32(0, Z_NULL, 0);
	n = crc32(n, (void*) &ptbl.header, sizeof(ptbl.header));
	hdr->crc32 = n;

	show(&ptbl);

	if (real_disk) {
  		write(fd, &ptbl, sizeof(ptbl));
		fsync(fd);

		if (ioctl(fd, BLKRRPART, 0)) {
			fprintf(stderr,"could not re-read partition table\n");
		}
		close(fd);
	}
	return 0;
}