gpttool

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 62b55300cfa6e9477329f71d20f7995e94fc88f1
parent 01fc835e641bb9fefbfbc51f6e070ca276328e69
Author: Brian Swetland <swetland@frotz.net>
Date:   Sun, 15 Dec 2013 23:06:29 -0800

various small changes and enhancements

- allow writing to a normal file as well as block devices
- write the secondary GPT
- include linux, linux-swap, and efi-boot uuids
- =<type> suffix allows specification of partition type uuid
- tweak the bogus mbr values
- disable safety-check on sda/sdb

Diffstat:
Mgpttool.c | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 98 insertions(+), 28 deletions(-)

diff --git a/gpttool.c b/gpttool.c @@ -21,22 +21,38 @@ #include <string.h> #include <fcntl.h> -#include <zlib.h> - #include <linux/fs.h> - #include <sys/stat.h> +#include <sys/ioctl.h> + +#include <zlib.h> typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; +#define _crc32(ptr,len) crc32(crc32(0,Z_NULL,0),(void*)(ptr),len) + const u8 partition_type_uuid[16] = { 0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44, 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7, }; +const u8 partition_type_efi[16] = { + 0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11, + 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b, +}; + +const u8 partition_type_linux[16] = { + 0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44, + 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7, +}; + +const u8 partition_type_swap[16] = { + 0x6d, 0xfd, 0x57, 0x06, 0xab, 0xa4, 0xc4, 0x43, + 0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f, +}; #define EFI_VERSION 0x00010000 #define EFI_MAGIC "EFI PART" @@ -95,12 +111,12 @@ void get_uuid(u8 *uuid) void init_mbr(u8 *mbr, u32 blocks) { mbr[0x1be] = 0x00; // nonbootable - mbr[0x1bf] = 0xFF; // bogus CHS - mbr[0x1c0] = 0xFF; - mbr[0x1c1] = 0xFF; + mbr[0x1bf] = 0x00; // bogus CHS + mbr[0x1c0] = 0x01; + mbr[0x1c1] = 0x00; mbr[0x1c2] = 0xEE; // GPT partition - mbr[0x1c3] = 0xFF; // bogus CHS + mbr[0x1c3] = 0xFE; // bogus CHS mbr[0x1c4] = 0xFF; mbr[0x1c5] = 0xFF; @@ -115,7 +131,7 @@ void init_mbr(u8 *mbr, u32 blocks) mbr[0x1ff] = 0xaa; } -int add_ptn(struct ptable *ptbl, u64 first, u64 last, const char *name) +int add_ptn(struct ptable *ptbl, u64 first, u64 last, const char *name, const u8 *type) { struct efi_header *hdr = &ptbl->header; struct efi_entry *entry = ptbl->entry; @@ -133,7 +149,7 @@ int add_ptn(struct ptable *ptbl, u64 first, u64 last, const char *name) for (n = 0; n < EFI_ENTRIES; n++, entry++) { if (entry->type_uuid[0]) continue; - memcpy(entry->type_uuid, partition_type_uuid, 16); + memcpy(entry->type_uuid, type, 16); get_uuid(entry->uniq_uuid); entry->first_lba = first; entry->last_lba = last; @@ -152,7 +168,8 @@ int usage(void) " gpttool read <disk>\n" " gpttool test [ <partition> ]*\n" "\n" - "partition: [<name>]:<size>[kmg] | @<file-of-partitions>\n" + "partition: [<name>]:<size>[kmg][=linux|=swap|=efi]\n" + " or: @<file-of-partitions>\n" ); return 0; } @@ -217,7 +234,9 @@ u64 parse_size(char *sz) int parse_ptn(struct ptable *ptbl, char *x) { + const u8 *type = partition_type_uuid; char *y = strchr(x, ':'); + char *z; u64 sz; if (!y) { @@ -226,6 +245,17 @@ int parse_ptn(struct ptable *ptbl, char *x) } *y++ = 0; + z = strchr(y, '='); + if (z) { + *z++ = 0; + if (!strcmp(z, "efi")) { + type = partition_type_efi; + } else if (!strcmp(z, "linux")) { + type = partition_type_linux; + } else if (!strcmp(z, "swap")) { + type = partition_type_swap; + } + } if (*y == 0) { sz = ptbl->header.last_lba - next_lba; } else { @@ -242,22 +272,32 @@ int parse_ptn(struct ptable *ptbl, char *x) return -1; } - if (x[0] && add_ptn(ptbl, next_lba, next_lba + sz - 1, x)) + if (x[0] && add_ptn(ptbl, next_lba, next_lba + sz - 1, x, type)) return -1; next_lba = next_lba + sz; return 0; } +void update_crc32(struct ptable *ptbl) { + u32 n; + + + n = _crc32((void*) ptbl->entry, sizeof(ptbl->entry)); + ptbl->header.entries_crc32 = n; + + ptbl->header.crc32 = 0; + n = _crc32((void*) &ptbl->header, sizeof(ptbl->header)); + ptbl->header.crc32 = n; +} + int main(int argc, char **argv) { struct ptable ptbl; - struct efi_entry *entry; struct efi_header *hdr = &ptbl.header; struct stat s; - u32 n; - u64 sz, blk; - int fd; + u64 sz; + int fd = -1; const char *device; int real_disk = 0; @@ -282,18 +322,29 @@ int main(int argc, char **argv) } if (real_disk) { +#if 0 if (!strcmp(device, "/dev/sda") || !strcmp(device, "/dev/sdb")) { fprintf(stderr,"error: refusing to partition sda or sdb\n"); return -1; } - +#endif fd = open(device, O_RDWR); if (fd < 0) { fprintf(stderr,"error: cannot open '%s'\n", device); return -1; } - if (ioctl(fd, BLKGETSIZE64, &sz)) { + if (fstat(fd, &s)) { + fprintf(stderr,"error: cannot stat '%s'\n", device); + return -1; + } + if (!S_ISBLK(s.st_mode) && !S_ISCHR(s.st_mode)) { + sz = s.st_size; + if (sz & 511) { + fprintf(stderr,"error: file size not multiple of 512\n"); + return -1; + } + } else if (ioctl(fd, BLKGETSIZE64, &sz)) { fprintf(stderr,"error: cannot query block device size\n"); return -1; } @@ -311,7 +362,7 @@ int main(int argc, char **argv) hdr->header_lba = 1; hdr->backup_lba = sz - 1; hdr->first_lba = 34; - hdr->last_lba = sz - 1; + hdr->last_lba = sz - 33; get_uuid(hdr->volume_uuid); hdr->entries_lba = 2; hdr->entries_count = 128; @@ -353,24 +404,43 @@ int main(int argc, char **argv) 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; + update_crc32(&ptbl); show(&ptbl); if (real_disk) { - write(fd, &ptbl, sizeof(ptbl)); + u64 off = (sz - 33) * 512; + if (write(fd, &ptbl, sizeof(ptbl)) != sizeof(ptbl)) { + fprintf(stderr,"error writing primary partition table\n"); + return -1; + } + if (lseek(fd, off, SEEK_SET) != off) { + fprintf(stderr,"error seeking to secondary partition table\n"); + return -1; + } + + /* reverse these for the secondary copy */ + hdr->header_lba = sz -1; + hdr->backup_lba = 1; + update_crc32(&ptbl); + + if (write(fd, &ptbl.entry, sizeof(ptbl) - 1024) != (sizeof(ptbl) - 1024)) { + fprintf(stderr,"error writing secondary partition table\n"); + return -1; + } + if (write(fd, &ptbl.header, 512) != 512) { + fprintf(stderr,"error writing secondary partition header\n"); + return -1; + } fsync(fd); if (ioctl(fd, BLKRRPART, 0)) { - fprintf(stderr,"could not re-read partition table\n"); + fprintf(stderr,"warning: could not re-read partition table\n"); + } + if (close(fd)) { + fprintf(stderr,"error writing data\n"); + return -1; } - close(fd); } return 0; }