1a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland/* system/core/gpttool/gpttool.c 2a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** 3a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** Copyright 2011, The Android Open Source Project 4a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** 5a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** Licensed under the Apache License, Version 2.0 (the "License"); 6a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** you may not use this file except in compliance with the License. 7a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** You may obtain a copy of the License at 8a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** 9a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** http://www.apache.org/licenses/LICENSE-2.0 10a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** 11a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** Unless required by applicable law or agreed to in writing, software 12a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** distributed under the License is distributed on an "AS IS" BASIS, 13a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** See the License for the specific language governing permissions and 15a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland** limitations under the License. 16a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland*/ 17a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 18a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland#include <stdio.h> 19a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland#include <stdlib.h> 20a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland#include <unistd.h> 21a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland#include <string.h> 22a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland#include <fcntl.h> 23a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 24a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland#include <zlib.h> 25a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 26a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland#include <linux/fs.h> 27a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 281aef06283286df8658b427885a6fffe9bdfeedberich cannings#include <sys/stat.h> 291aef06283286df8658b427885a6fffe9bdfeedberich cannings 30a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandtypedef unsigned char u8; 31a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandtypedef unsigned short u16; 32a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandtypedef unsigned int u32; 33a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandtypedef unsigned long long u64; 34a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 35a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandconst u8 partition_type_uuid[16] = { 36a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44, 37a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7, 38a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland}; 39a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 40a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 41a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland#define EFI_VERSION 0x00010000 42a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland#define EFI_MAGIC "EFI PART" 43a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland#define EFI_ENTRIES 128 44a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland#define EFI_NAMELEN 36 45a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 46a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandstruct efi_header { 47a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u8 magic[8]; 48a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 49a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u32 version; 50a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u32 header_sz; 51a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 52a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u32 crc32; 53a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u32 reserved; 54a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 55a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u64 header_lba; 56a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u64 backup_lba; 57a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u64 first_lba; 58a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u64 last_lba; 59a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 60a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u8 volume_uuid[16]; 61a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 62a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u64 entries_lba; 63a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 64a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u32 entries_count; 65a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u32 entries_size; 66a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u32 entries_crc32; 67a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland} __attribute__((packed)); 68a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 69a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandstruct efi_entry { 70a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u8 type_uuid[16]; 71a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u8 uniq_uuid[16]; 72a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u64 first_lba; 73a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u64 last_lba; 74a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u64 attr; 75a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u16 name[EFI_NAMELEN]; 76a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland}; 77a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 78a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandstruct ptable { 79a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u8 mbr[512]; 80a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland union { 81a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland struct efi_header header; 82a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u8 block[512]; 83a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland }; 84a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland struct efi_entry entry[EFI_ENTRIES]; 85a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland}; 86a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 87a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandvoid get_uuid(u8 *uuid) 88a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland{ 89a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland int fd; 90a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fd = open("/dev/urandom", O_RDONLY); 91a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland read(fd, uuid, 16); 92a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland close(fd); 93a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland} 94a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 95a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandvoid init_mbr(u8 *mbr, u32 blocks) 96a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland{ 97a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1be] = 0x00; // nonbootable 98a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1bf] = 0xFF; // bogus CHS 99a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1c0] = 0xFF; 100a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1c1] = 0xFF; 101a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 102a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1c2] = 0xEE; // GPT partition 103a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1c3] = 0xFF; // bogus CHS 104a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1c4] = 0xFF; 105a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1c5] = 0xFF; 106a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 107a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1c6] = 0x01; // start 108a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1c7] = 0x00; 109a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1c8] = 0x00; 110a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1c9] = 0x00; 111a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 112a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland memcpy(mbr + 0x1ca, &blocks, sizeof(u32)); 113a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 114a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1fe] = 0x55; 115a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland mbr[0x1ff] = 0xaa; 116a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland} 117a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 118a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandint add_ptn(struct ptable *ptbl, u64 first, u64 last, const char *name) 119a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland{ 120a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland struct efi_header *hdr = &ptbl->header; 121a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland struct efi_entry *entry = ptbl->entry; 122a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland unsigned n; 123a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 124a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (first < 34) { 125a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"partition '%s' overlaps partition table\n", name); 126a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 127a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 128a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 129a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (last > hdr->last_lba) { 130a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"partition '%s' does not fit on disk\n", name); 131a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 132a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 133a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland for (n = 0; n < EFI_ENTRIES; n++, entry++) { 134a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (entry->type_uuid[0]) 135a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland continue; 136a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland memcpy(entry->type_uuid, partition_type_uuid, 16); 137a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland get_uuid(entry->uniq_uuid); 138a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland entry->first_lba = first; 139a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland entry->last_lba = last; 140a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland for (n = 0; (n < EFI_NAMELEN) && *name; n++) 141a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland entry->name[n] = *name++; 142a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return 0; 143a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 144a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"out of partition table entries\n"); 145a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 146a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland} 147a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 148a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandint usage(void) 149a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland{ 150a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr, 151a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland "usage: gpttool write <disk> [ <partition> ]*\n" 152a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland " gpttool read <disk>\n" 153a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland " gpttool test [ <partition> ]*\n" 154a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland "\n" 155a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland "partition: [<name>]:<size>[kmg] | @<file-of-partitions>\n" 156a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland ); 157a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return 0; 158a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland} 159a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 160a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandvoid show(struct ptable *ptbl) 161a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland{ 162a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland struct efi_entry *entry = ptbl->entry; 163a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland unsigned n, m; 164a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland char name[EFI_NAMELEN]; 165a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 166a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"ptn start block end block name\n"); 167a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"---- ------------- ------------- --------------------\n"); 168a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 169a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland for (n = 0; n < EFI_ENTRIES; n++, entry++) { 170a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (entry->type_uuid[0] == 0) 171a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland break; 172a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland for (m = 0; m < EFI_NAMELEN; m++) { 173a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland name[m] = entry->name[m] & 127; 174a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 175a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland name[m] = 0; 176a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"#%03d %13lld %13lld %s\n", 177a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland n + 1, entry->first_lba, entry->last_lba, name); 178a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 179a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland} 180a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 181a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandu64 find_next_lba(struct ptable *ptbl) 182a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland{ 183a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland struct efi_entry *entry = ptbl->entry; 184a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland unsigned n; 185a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u64 a = 0; 186a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland for (n = 0; n < EFI_ENTRIES; n++, entry++) { 187a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if ((entry->last_lba + 1) > a) 188a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland a = entry->last_lba + 1; 189a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 190a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return a; 191a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland} 192a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 193a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandu64 next_lba = 0; 194a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 195a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandu64 parse_size(char *sz) 196a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland{ 197a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland int l = strlen(sz); 198a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u64 n = strtoull(sz, 0, 10); 199a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (l) { 200a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland switch(sz[l-1]){ 201a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland case 'k': 202a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland case 'K': 203a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland n *= 1024; 204a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland break; 205a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland case 'm': 206a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland case 'M': 207a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland n *= (1024 * 1024); 208a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland break; 209a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland case 'g': 210a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland case 'G': 211a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland n *= (1024 * 1024 * 1024); 212a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland break; 213a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 214a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 215a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return n; 216a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland} 217a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 218a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandint parse_ptn(struct ptable *ptbl, char *x) 219a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland{ 220a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland char *y = strchr(x, ':'); 221a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u64 sz; 222a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 223a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (!y) { 224a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"invalid partition entry: %s\n", x); 225a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 226a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 227a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland *y++ = 0; 228a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 229a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (*y == 0) { 230a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland sz = ptbl->header.last_lba - next_lba; 231a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } else { 232a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland sz = parse_size(y); 233a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (sz & 511) { 234a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"partition size must be multiple of 512\n"); 235a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 236a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 237a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland sz /= 512; 238a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 239a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 240a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (sz == 0) { 241a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"zero size partitions not allowed\n"); 242a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 243a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 244a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 245a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (x[0] && add_ptn(ptbl, next_lba, next_lba + sz - 1, x)) 246a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 247a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 248a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland next_lba = next_lba + sz; 249a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return 0; 250a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland} 251a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 252a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetlandint main(int argc, char **argv) 253a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland{ 254a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland struct ptable ptbl; 255a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland struct efi_entry *entry; 256a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland struct efi_header *hdr = &ptbl.header; 257a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland struct stat s; 258a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u32 n; 259a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland u64 sz, blk; 260a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland int fd; 261a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland const char *device; 262a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland int real_disk = 0; 263a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 264a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (argc < 2) 265a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return usage(); 266a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 267a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (!strcmp(argv[1], "write")) { 268a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (argc < 3) 269a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return usage(); 270a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland device = argv[2]; 271a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland argc -= 2; 272a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland argv += 2; 273a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland real_disk = 1; 274a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } else if (!strcmp(argv[1], "test")) { 275a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland argc -= 1; 276a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland argv += 1; 277a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland real_disk = 0; 278a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland sz = 2097152 * 16; 279a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"< simulating 16GB disk >\n\n"); 280a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } else { 281a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return usage(); 282a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 283a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 284a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (real_disk) { 285a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (!strcmp(device, "/dev/sda") || 286a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland !strcmp(device, "/dev/sdb")) { 287a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"error: refusing to partition sda or sdb\n"); 288a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 289a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 290a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 291a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fd = open(device, O_RDWR); 292a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (fd < 0) { 293a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"error: cannot open '%s'\n", device); 294a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 295a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 296a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (ioctl(fd, BLKGETSIZE64, &sz)) { 297a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"error: cannot query block device size\n"); 298a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 299a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 300a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland sz /= 512; 301a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"blocks %lld\n", sz); 302a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 303a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 304a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland memset(&ptbl, 0, sizeof(ptbl)); 305a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 306a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland init_mbr(ptbl.mbr, sz - 1); 307a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 308a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland memcpy(hdr->magic, EFI_MAGIC, sizeof(hdr->magic)); 309a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland hdr->version = EFI_VERSION; 310a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland hdr->header_sz = sizeof(struct efi_header); 311a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland hdr->header_lba = 1; 312a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland hdr->backup_lba = sz - 1; 313a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland hdr->first_lba = 34; 314a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland hdr->last_lba = sz - 1; 315a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland get_uuid(hdr->volume_uuid); 316a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland hdr->entries_lba = 2; 317a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland hdr->entries_count = 128; 318a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland hdr->entries_size = sizeof(struct efi_entry); 319a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 320a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland while (argc > 1) { 321a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (argv[1][0] == '@') { 322a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland char line[256], *p; 323a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland FILE *f; 324a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland f = fopen(argv[1] + 1, "r"); 325a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (!f) { 326a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"cannot read partitions from '%s\n", argv[1]); 327a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 328a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 329a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland while (fgets(line, sizeof(line), f)) { 330a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland p = line + strlen(line); 331a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland while (p > line) { 332a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland p--; 333a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (*p > ' ') 334a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland break; 335a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland *p = 0; 336a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 337a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland p = line; 338a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland while (*p && (*p <= ' ')) 339a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland p++; 340a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (*p == '#') 341a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland continue; 342a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (*p == 0) 343a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland continue; 344a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (parse_ptn(&ptbl, p)) 345a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 346a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 347a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fclose(f); 348a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } else { 349a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (parse_ptn(&ptbl, argv[1])) 350a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return -1; 351a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 352a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland argc--; 353a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland argv++; 354a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 355a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 356a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland n = crc32(0, Z_NULL, 0); 357a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland n = crc32(n, (void*) ptbl.entry, sizeof(ptbl.entry)); 358a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland hdr->entries_crc32 = n; 359a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 360a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland n = crc32(0, Z_NULL, 0); 361a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland n = crc32(n, (void*) &ptbl.header, sizeof(ptbl.header)); 362a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland hdr->crc32 = n; 363a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 364a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland show(&ptbl); 365a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 366a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (real_disk) { 367a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland write(fd, &ptbl, sizeof(ptbl)); 368a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fsync(fd); 369a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland 370a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland if (ioctl(fd, BLKRRPART, 0)) { 371a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland fprintf(stderr,"could not re-read partition table\n"); 372a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 373a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland close(fd); 374a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland } 375a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland return 0; 376a360a77294600cd679d4ea69b0b24e217bd02a9eBrian Swetland} 377