1cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 23dcf9dce04301d6d735f265652625fffb6758430Randall Spangler * Use of this source code is governed by a BSD-style license that can be 33dcf9dce04301d6d735f265652625fffb6758430Randall Spangler * found in the LICENSE file. 43dcf9dce04301d6d735f265652625fffb6758430Randall Spangler */ 53dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 60c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "sysincludes.h" 70c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson 83dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#include "cgptlib.h" 93dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#include "cgptlib_internal.h" 103dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#include "crc32.h" 113dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#include "gpt.h" 127c2beb08380410ca6847abdac23e11ded2d1b625Dan Ehrenberg#include "gpt_misc.h" 133dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#include "utility.h" 143dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 153200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyenconst static int SECTOR_SIZE = 512; 163200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen 173200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyensize_t CalculateEntriesSectors(GptHeader* h) { 183200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen size_t bytes = h->number_of_entries * h->size_of_entry; 193200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen size_t ret = (bytes + SECTOR_SIZE - 1) / SECTOR_SIZE; 203200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen return ret; 213200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen} 223dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 23cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglerint CheckParameters(GptData *gpt) 24cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 25cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Currently, we only support 512-byte sectors. */ 263200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen if (gpt->sector_bytes != SECTOR_SIZE) 27cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return GPT_ERROR_INVALID_SECTOR_SIZE; 28cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 29cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* 30b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg * gpt_drive_sectors should be reasonable. It cannot be unset, and it 31b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg * cannot differ from streaming_drive_sectors if the GPT structs are 32b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg * stored on same device. 336ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen */ 346ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen if (gpt->gpt_drive_sectors == 0 || 35b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg (!(gpt->flags & GPT_FLAG_EXTERNAL) && 36b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg gpt->gpt_drive_sectors != gpt->streaming_drive_sectors)) { 376ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen return GPT_ERROR_INVALID_SECTOR_NUMBER; 386ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen } 396ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen 406ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen /* 41cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * Sector count of a drive should be reasonable. If the given value is 42cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * too small to contain basic GPT structure (PMBR + Headers + Entries), 43f3f7fca07fbcb6bb9655a71257f09c71b0a1458dDan Ehrenberg * the value is wrong. 44cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler */ 45f3f7fca07fbcb6bb9655a71257f09c71b0a1458dDan Ehrenberg if (gpt->gpt_drive_sectors < 46f3f7fca07fbcb6bb9655a71257f09c71b0a1458dDan Ehrenberg (1 + 2 * (1 + MIN_NUMBER_OF_ENTRIES / 47f3f7fca07fbcb6bb9655a71257f09c71b0a1458dDan Ehrenberg (SECTOR_SIZE / sizeof(GptEntry))))) 48cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return GPT_ERROR_INVALID_SECTOR_NUMBER; 49cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 50cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return GPT_SUCCESS; 513dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 523dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 53cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangleruint32_t HeaderCrc(GptHeader *h) 54cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 55cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler uint32_t crc32, original_crc32; 563dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 57cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Original CRC is calculated with the CRC field 0. */ 58cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler original_crc32 = h->header_crc32; 59cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler h->header_crc32 = 0; 60cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler crc32 = Crc32((const uint8_t *)h, h->size); 61cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler h->header_crc32 = original_crc32; 623dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 63cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return crc32; 643dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 653dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 66b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenbergint CheckHeader(GptHeader *h, int is_secondary, 67b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg uint64_t streaming_drive_sectors, 68b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg uint64_t gpt_drive_sectors, uint32_t flags) 69cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 70cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (!h) 71cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 72cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 73cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* 74cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * Make sure we're looking at a header of reasonable size before 75cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * attempting to calculate CRC. 76cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler */ 77cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (Memcmp(h->signature, GPT_HEADER_SIGNATURE, 78cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GPT_HEADER_SIGNATURE_SIZE) && 79cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler Memcmp(h->signature, GPT_HEADER_SIGNATURE2, 80cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GPT_HEADER_SIGNATURE_SIZE)) 81cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 82cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (h->revision != GPT_HEADER_REVISION) 83cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 84cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (h->size < MIN_SIZE_OF_HEADER || h->size > MAX_SIZE_OF_HEADER) 85cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 86cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 87cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Check CRC before looking at remaining fields */ 88cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (HeaderCrc(h) != h->header_crc32) 89cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 90cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 91cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Reserved fields must be zero. */ 92cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (h->reserved_zero) 93cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 94cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 95cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Could check that padding is zero, but that doesn't matter to us. */ 96cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 97cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* 98cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * If entry size is different than our struct, we won't be able to 99cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * parse it. Technically, any size 2^N where N>=7 is valid. 100cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler */ 101cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (h->size_of_entry != sizeof(GptEntry)) 102cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 103cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if ((h->number_of_entries < MIN_NUMBER_OF_ENTRIES) || 104cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler (h->number_of_entries > MAX_NUMBER_OF_ENTRIES) || 105b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg (!(flags & GPT_FLAG_EXTERNAL) && 106f3f7fca07fbcb6bb9655a71257f09c71b0a1458dDan Ehrenberg h->number_of_entries != MAX_NUMBER_OF_ENTRIES)) 107cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 108cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 109cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* 110cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * Check locations for the header and its entries. The primary 111cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * immediately follows the PMBR, and is followed by its entries. The 112cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * secondary is at the end of the drive, preceded by its entries. 113cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler */ 114cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (is_secondary) { 115a524a3a51591618c1395cb9e1238ee72b3f5e767Dan Ehrenberg if (h->my_lba != gpt_drive_sectors - GPT_HEADER_SECTORS) 116cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 1173200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen if (h->entries_lba != h->my_lba - CalculateEntriesSectors(h)) 118cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 119cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler } else { 12088458d9b5281aca162821a369707781ac9abb44eNam T. Nguyen if (h->my_lba != GPT_PMBR_SECTORS) 121cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 122a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen if (h->entries_lba < h->my_lba + 1) 123cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 124cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler } 125cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 1266ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen /* FirstUsableLBA <= LastUsableLBA. */ 1276ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen if (h->first_usable_lba > h->last_usable_lba) 1286ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen return 1; 1296ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen 130b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg if (flags & GPT_FLAG_EXTERNAL) { 131b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg if (h->last_usable_lba >= streaming_drive_sectors) { 1326ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen return 1; 1336ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen } 1346ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen return 0; 1356ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen } 1366ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen 137cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* 138cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * FirstUsableLBA must be after the end of the primary GPT table array. 139cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * LastUsableLBA must be before the start of the secondary GPT table 1406ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen * array. 141cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler */ 142a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen /* TODO(namnguyen): Also check for padding between header & entries. */ 1433200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen if (h->first_usable_lba < 2 + CalculateEntriesSectors(h)) 144cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 145b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg if (h->last_usable_lba >= 1463200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen streaming_drive_sectors - 1 - CalculateEntriesSectors(h)) 147cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 148cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 149cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Success */ 150cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 0; 1513dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 1523dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 153cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglerint IsKernelEntry(const GptEntry *e) 154cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 155cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler static Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL; 156cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return !Memcmp(&e->type, &chromeos_kernel, sizeof(Guid)); 1573dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 1583dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 159cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglerint CheckEntries(GptEntry *entries, GptHeader *h) 160cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 1615ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen if (!entries) 1625ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen return GPT_ERROR_INVALID_ENTRIES; 163cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptEntry *entry; 164cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler uint32_t crc32; 165cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler uint32_t i; 166cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 167cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Check CRC before examining entries. */ 168cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler crc32 = Crc32((const uint8_t *)entries, 169cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler h->size_of_entry * h->number_of_entries); 170cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (crc32 != h->entries_crc32) 171cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return GPT_ERROR_CRC_CORRUPTED; 172cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 173cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Check all entries. */ 174cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler for (i = 0, entry = entries; i < h->number_of_entries; i++, entry++) { 175cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptEntry *e2; 176cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler uint32_t i2; 177cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 178cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (IsUnusedEntry(entry)) 179cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler continue; 180cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 181cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Entry must be in valid region. */ 182cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if ((entry->starting_lba < h->first_usable_lba) || 183cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler (entry->ending_lba > h->last_usable_lba) || 184cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler (entry->ending_lba < entry->starting_lba)) 185cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return GPT_ERROR_OUT_OF_REGION; 186cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 187cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Entry must not overlap other entries. */ 188cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler for (i2 = 0, e2 = entries; i2 < h->number_of_entries; 189cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler i2++, e2++) { 190cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (i2 == i || IsUnusedEntry(e2)) 191cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler continue; 192cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 193cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if ((entry->starting_lba >= e2->starting_lba) && 194cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler (entry->starting_lba <= e2->ending_lba)) 195cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return GPT_ERROR_START_LBA_OVERLAP; 196cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if ((entry->ending_lba >= e2->starting_lba) && 197cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler (entry->ending_lba <= e2->ending_lba)) 198cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return GPT_ERROR_END_LBA_OVERLAP; 199cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 200cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* UniqueGuid field must be unique. */ 201cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (0 == Memcmp(&entry->unique, &e2->unique, 202cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler sizeof(Guid))) 203cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return GPT_ERROR_DUP_GUID; 204cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler } 205cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler } 206cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 207cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Success */ 208cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 0; 2093dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 2103dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 211cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglerint HeaderFieldsSame(GptHeader *h1, GptHeader *h2) 212cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 213cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (Memcmp(h1->signature, h2->signature, sizeof(h1->signature))) 214cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 215cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (h1->revision != h2->revision) 216cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 217cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (h1->size != h2->size) 218cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 219cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (h1->reserved_zero != h2->reserved_zero) 220cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 221cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (h1->first_usable_lba != h2->first_usable_lba) 222cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 223cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (h1->last_usable_lba != h2->last_usable_lba) 224cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 225cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (Memcmp(&h1->disk_uuid, &h2->disk_uuid, sizeof(Guid))) 226cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 227cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (h1->number_of_entries != h2->number_of_entries) 228cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 229cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (h1->size_of_entry != h2->size_of_entry) 230cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 231cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (h1->entries_crc32 != h2->entries_crc32) 232cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 1; 233cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 234cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return 0; 2353dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 2363dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 237cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglerint GptSanityCheck(GptData *gpt) 238cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 239cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler int retval; 240cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptHeader *header1 = (GptHeader *)(gpt->primary_header); 241cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptHeader *header2 = (GptHeader *)(gpt->secondary_header); 242cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptEntry *entries1 = (GptEntry *)(gpt->primary_entries); 243cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptEntry *entries2 = (GptEntry *)(gpt->secondary_entries); 244cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptHeader *goodhdr = NULL; 245cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 246cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->valid_headers = 0; 247cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->valid_entries = 0; 248cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 249cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler retval = CheckParameters(gpt); 250cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (retval != GPT_SUCCESS) 251cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return retval; 252cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 253cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Check both headers; we need at least one valid header. */ 254b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg if (0 == CheckHeader(header1, 0, gpt->streaming_drive_sectors, 255b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg gpt->gpt_drive_sectors, gpt->flags)) { 256cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->valid_headers |= MASK_PRIMARY; 257cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler goodhdr = header1; 258cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler } 259b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg if (0 == CheckHeader(header2, 1, gpt->streaming_drive_sectors, 260b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg gpt->gpt_drive_sectors, gpt->flags)) { 261cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->valid_headers |= MASK_SECONDARY; 262cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (!goodhdr) 263cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler goodhdr = header2; 264cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler } 265cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 266cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (!gpt->valid_headers) 267cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return GPT_ERROR_INVALID_HEADERS; 268cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 269cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* 270cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * Check if entries are valid. 271cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * 272cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * Note that we use the same header in both checks. This way we'll 273cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * catch the case where (header1,entries1) and (header2,entries2) are 274cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * both valid, but (entries1 != entries2). 275cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler */ 276cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (0 == CheckEntries(entries1, goodhdr)) 277cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->valid_entries |= MASK_PRIMARY; 278cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (0 == CheckEntries(entries2, goodhdr)) 279cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->valid_entries |= MASK_SECONDARY; 280cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 281cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* 282cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * If both headers are good but neither entries were good, check the 283cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * entries with the secondary header. 284cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler */ 285cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (MASK_BOTH == gpt->valid_headers && !gpt->valid_entries) { 286cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (0 == CheckEntries(entries1, header2)) 287cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->valid_entries |= MASK_PRIMARY; 288cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (0 == CheckEntries(entries2, header2)) 289cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->valid_entries |= MASK_SECONDARY; 290cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (gpt->valid_entries) { 291cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* 292cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * Sure enough, header2 had a good CRC for one of the 293cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * entries. Mark header1 invalid, so we'll update its 294cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * entries CRC. 295cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler */ 296cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->valid_headers &= ~MASK_PRIMARY; 297cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler goodhdr = header2; 298cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler } 299cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler } 300cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 301cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (!gpt->valid_entries) 302cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return GPT_ERROR_INVALID_ENTRIES; 303cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 304cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* 305cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * Now that we've determined which header contains a good CRC for 306cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler * the entries, make sure the headers are otherwise identical. 307cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler */ 308cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (MASK_BOTH == gpt->valid_headers && 309cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 0 != HeaderFieldsSame(header1, header2)) 310cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->valid_headers &= ~MASK_SECONDARY; 311cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 312cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return GPT_SUCCESS; 3133dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 3143dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 315cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglervoid GptRepair(GptData *gpt) 316cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 317cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptHeader *header1 = (GptHeader *)(gpt->primary_header); 318cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptHeader *header2 = (GptHeader *)(gpt->secondary_header); 319cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptEntry *entries1 = (GptEntry *)(gpt->primary_entries); 320cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptEntry *entries2 = (GptEntry *)(gpt->secondary_entries); 321cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler int entries_size; 322cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 323cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Need at least one good header and one good set of entries. */ 324cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (MASK_NONE == gpt->valid_headers || MASK_NONE == gpt->valid_entries) 325cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return; 326cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 327cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Repair headers if necessary */ 328cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (MASK_PRIMARY == gpt->valid_headers) { 329cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Primary is good, secondary is bad */ 330cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler Memcpy(header2, header1, sizeof(GptHeader)); 331a524a3a51591618c1395cb9e1238ee72b3f5e767Dan Ehrenberg header2->my_lba = gpt->gpt_drive_sectors - GPT_HEADER_SECTORS; 33288458d9b5281aca162821a369707781ac9abb44eNam T. Nguyen header2->alternate_lba = GPT_PMBR_SECTORS; /* Second sector. */ 3333200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen header2->entries_lba = header2->my_lba - CalculateEntriesSectors(header1); 334cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler header2->header_crc32 = HeaderCrc(header2); 335cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->modified |= GPT_MODIFIED_HEADER2; 336cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler } 337cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler else if (MASK_SECONDARY == gpt->valid_headers) { 338cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Secondary is good, primary is bad */ 339cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler Memcpy(header1, header2, sizeof(GptHeader)); 34088458d9b5281aca162821a369707781ac9abb44eNam T. Nguyen header1->my_lba = GPT_PMBR_SECTORS; /* Second sector. */ 341b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg header1->alternate_lba = 342b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg gpt->streaming_drive_sectors - GPT_HEADER_SECTORS; 343a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen /* TODO (namnguyen): Preserve (header, entries) padding. */ 344cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler header1->entries_lba = header1->my_lba + 1; 345cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler header1->header_crc32 = HeaderCrc(header1); 346cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->modified |= GPT_MODIFIED_HEADER1; 347cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler } 348cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->valid_headers = MASK_BOTH; 349cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler 350cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Repair entries if necessary */ 351cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler entries_size = header1->size_of_entry * header1->number_of_entries; 352cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (MASK_PRIMARY == gpt->valid_entries) { 353cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Primary is good, secondary is bad */ 354cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler Memcpy(entries2, entries1, entries_size); 355cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->modified |= GPT_MODIFIED_ENTRIES2; 356cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler } 357cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler else if (MASK_SECONDARY == gpt->valid_entries) { 358cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler /* Secondary is good, primary is bad */ 359cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler Memcpy(entries1, entries2, entries_size); 360cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->modified |= GPT_MODIFIED_ENTRIES1; 361cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler } 362cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler gpt->valid_entries = MASK_BOTH; 3633dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 3643dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 365cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglerint GetEntrySuccessful(const GptEntry *e) 366cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 367cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >> 368cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET; 3693dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 3703dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 371cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglerint GetEntryPriority(const GptEntry *e) 372cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 373cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_PRIORITY_MASK) >> 374cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler CGPT_ATTRIBUTE_PRIORITY_OFFSET; 3753dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 3763dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 377cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglerint GetEntryTries(const GptEntry *e) 378cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 379cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_TRIES_MASK) >> 380cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler CGPT_ATTRIBUTE_TRIES_OFFSET; 3813dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 3823dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 383cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglervoid SetEntrySuccessful(GptEntry *e, int successful) 384cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 385cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler if (successful) 386cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler e->attrs.fields.gpt_att |= CGPT_ATTRIBUTE_SUCCESSFUL_MASK; 387cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler else 388cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler e->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_SUCCESSFUL_MASK; 3893dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 3903dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 391cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglervoid SetEntryPriority(GptEntry *e, int priority) 392cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 393cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler e->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_PRIORITY_MASK; 394cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler e->attrs.fields.gpt_att |= 395cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler (priority << CGPT_ATTRIBUTE_PRIORITY_OFFSET) & 396cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler CGPT_ATTRIBUTE_PRIORITY_MASK; 3973dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 3983dcf9dce04301d6d735f265652625fffb6758430Randall Spangler 399cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglervoid SetEntryTries(GptEntry *e, int tries) 400cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 401cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler e->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_TRIES_MASK; 402cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler e->attrs.fields.gpt_att |= (tries << CGPT_ATTRIBUTE_TRIES_OFFSET) & 403cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler CGPT_ATTRIBUTE_TRIES_MASK; 4043dcf9dce04301d6d735f265652625fffb6758430Randall Spangler} 4055deb67f22507481cf5cb8f991976a9969fa90a22Bill Richardson 406cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglervoid GetCurrentKernelUniqueGuid(GptData *gpt, void *dest) 407cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler{ 408cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptEntry *entries = (GptEntry *)gpt->primary_entries; 409cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler GptEntry *e = entries + gpt->current_kernel; 410cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler Memcpy(dest, &e->unique, sizeof(Guid)); 4115deb67f22507481cf5cb8f991976a9969fa90a22Bill Richardson} 41265d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 4135c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulkvoid GptModified(GptData *gpt) { 4145c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk GptHeader *header = (GptHeader *)gpt->primary_header; 4155c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk 4165c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk /* Update the CRCs */ 4175c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk header->entries_crc32 = Crc32(gpt->primary_entries, 4185c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk header->size_of_entry * 4195c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk header->number_of_entries); 4205c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk header->header_crc32 = HeaderCrc(header); 4215c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk gpt->modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1; 4225c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk 4235c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk /* 4245c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk * Use the repair function to update the other copy of the GPT. This 4255c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk * is a tad inefficient, but is much faster than the disk I/O to update 4265c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk * the GPT on disk so it doesn't matter. 4275c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk */ 4285c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk gpt->valid_headers = MASK_PRIMARY; 4295c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk gpt->valid_entries = MASK_PRIMARY; 4305c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk GptRepair(gpt); 4315c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk} 4325c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk 4335c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk 434cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spanglerconst char *GptErrorText(int error_code) 43565d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury{ 436cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler switch(error_code) { 437cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler case GPT_SUCCESS: 438cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "none"; 43965d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 440cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler case GPT_ERROR_NO_VALID_KERNEL: 441cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "Invalid kernel"; 44265d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 443cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler case GPT_ERROR_INVALID_HEADERS: 444cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "Invalid headers"; 44565d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 446cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler case GPT_ERROR_INVALID_ENTRIES: 447cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "Invalid entries"; 44865d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 449cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler case GPT_ERROR_INVALID_SECTOR_SIZE: 450cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "Invalid sector size"; 45165d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 452cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler case GPT_ERROR_INVALID_SECTOR_NUMBER: 453cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "Invalid sector number"; 45465d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 455cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler case GPT_ERROR_INVALID_UPDATE_TYPE: 456cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "Invalid update type"; 45765d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 458cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler case GPT_ERROR_CRC_CORRUPTED: 459cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "Entries' crc corrupted"; 46065d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 461cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler case GPT_ERROR_OUT_OF_REGION: 462cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "Entry outside of valid region"; 46365d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 464cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler case GPT_ERROR_START_LBA_OVERLAP: 465cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "Starting LBA overlaps"; 46665d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 467cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler case GPT_ERROR_END_LBA_OVERLAP: 468cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "Ending LBA overlaps"; 46965d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 470cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler case GPT_ERROR_DUP_GUID: 471cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "Duplicated GUID"; 47265d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury 4735c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk case GPT_ERROR_INVALID_FLASH_GEOMETRY: 4745c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk return "Invalid flash geometry"; 4755c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk 4765c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk case GPT_ERROR_NO_SUCH_ENTRY: 4775c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk return "No entry found"; 4785c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk 479cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler default: 480cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler break; 481cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler }; 482cefe12c105a91e6ee9f44bca218bd6e4f89bcb71Randall Spangler return "Unknown"; 48365d3c277a2098d6149fb79f7881da5d78133ae57Vadim Bendebury} 484