| OLD | NEW | 
|    1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |    1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 
|    2  * Use of this source code is governed by a BSD-style license that can be |    2  * Use of this source code is governed by a BSD-style license that can be | 
|    3  * found in the LICENSE file. |    3  * found in the LICENSE file. | 
|    4  */ |    4  */ | 
|    5  |    5  | 
|    6 #include "cgpt.h" |    6 #include "cgpt.h" | 
|    7 #include <string.h> |    7 #include <string.h> | 
 |    8 #include "cgpt_internal.h" | 
 |    9 #include "crc32.h" | 
|    8 #include "gpt.h" |   10 #include "gpt.h" | 
 |   11 #include "quick_sort.h" | 
|    9 #include "utility.h" |   12 #include "utility.h" | 
|   10  |   13  | 
 |   14 /* Macro to invalidate a GPT header/entries */ | 
 |   15 #define INVALIDATE_HEADER(valid_headers, index) \ | 
 |   16   do { \ | 
 |   17     valid_headers &= ~(1<<index); \ | 
 |   18   } while (0) | 
 |   19 #define INVALIDATE_ENTRIES(valid_entries, index) \ | 
 |   20   do { \ | 
 |   21     valid_entries &= ~(1<<index); \ | 
 |   22   } while (0) | 
 |   23  | 
 |   24 /* Checks if sector_bytes and drive_sectors are valid values. */ | 
 |   25 int CheckParameters(GptData *gpt) { | 
 |   26   /* Currently, we only support 512-byte sector. In the future, we may support | 
 |   27    * larger sector. */ | 
 |   28   if (gpt->sector_bytes != 512) | 
 |   29     return GPT_ERROR_INVALID_SECTOR_SIZE; | 
 |   30  | 
 |   31   /* The sector number of a drive should be reasonable. If the given value is | 
 |   32    * too small to contain basic GPT structure (PMBR + Headers + Entries), | 
 |   33    * the value is wrong. */ | 
 |   34   if (gpt->drive_sectors < (GPT_PMBR_SECTOR + | 
 |   35                             GPT_HEADER_SECTOR * 2 + | 
 |   36                             GPT_ENTRIES_SECTORS * 2)) | 
 |   37     return GPT_ERROR_INVALID_SECTOR_NUMBER; | 
 |   38  | 
 |   39   return GPT_SUCCESS; | 
 |   40 } | 
 |   41  | 
 |   42 /* Expects header signature should be GPT_HEADER_SIGNATURE. */ | 
 |   43 uint32_t CheckHeaderSignature(GptData *gpt) { | 
 |   44   uint32_t valid_headers = MASK_BOTH; | 
 |   45   GptHeader *headers[] = { | 
 |   46     (GptHeader*)gpt->primary_header, | 
 |   47     (GptHeader*)gpt->secondary_header, | 
 |   48   }; | 
 |   49   int i; | 
 |   50  | 
 |   51   for (i = PRIMARY; i <= SECONDARY; ++i) { | 
 |   52     if (Memcmp(headers[i]->signature, | 
 |   53                GPT_HEADER_SIGNATURE, | 
 |   54                GPT_HEADER_SIGNATURE_SIZE)) { | 
 |   55       INVALIDATE_HEADER(valid_headers, i); | 
 |   56     } | 
 |   57   } | 
 |   58   return valid_headers; | 
 |   59 } | 
 |   60  | 
 |   61 /* The header revision should be GPT_HEADER_REVISION. */ | 
 |   62 uint32_t CheckRevision(GptData *gpt) { | 
 |   63   uint32_t valid_headers = MASK_BOTH; | 
 |   64   GptHeader *headers[] = { | 
 |   65     (GptHeader*)gpt->primary_header, | 
 |   66     (GptHeader*)gpt->secondary_header, | 
 |   67   }; | 
 |   68   int i; | 
 |   69  | 
 |   70   for (i = PRIMARY; i <= SECONDARY; ++i) { | 
 |   71     if (headers[i]->revision != GPT_HEADER_REVISION) | 
 |   72       INVALIDATE_HEADER(valid_headers, i); | 
 |   73   } | 
 |   74   return valid_headers; | 
 |   75 } | 
 |   76  | 
 |   77 /* A valid header size should be between MIN_SIZE_OF_HEADER and | 
 |   78  * MAX_SIZE_OF_HEADER. */ | 
 |   79 uint32_t CheckSize(GptData *gpt) { | 
 |   80   uint32_t valid_headers = MASK_BOTH; | 
 |   81   GptHeader *headers[] = { | 
 |   82     (GptHeader*)gpt->primary_header, | 
 |   83     (GptHeader*)gpt->secondary_header, | 
 |   84   }; | 
 |   85   int i; | 
 |   86  | 
 |   87   for (i = PRIMARY; i <= SECONDARY; ++i) { | 
 |   88     if ((headers[i]->size < MIN_SIZE_OF_HEADER) || | 
 |   89         (headers[i]->size > MAX_SIZE_OF_HEADER)) | 
 |   90       INVALIDATE_HEADER(valid_headers, i); | 
 |   91   } | 
 |   92   return valid_headers; | 
 |   93 } | 
 |   94  | 
 |   95 /* Reserved and padding fields should be zero. */ | 
 |   96 uint32_t CheckReservedFields(GptData *gpt) { | 
 |   97   uint32_t valid_headers = MASK_BOTH; | 
 |   98   GptHeader *headers[] = { | 
 |   99     (GptHeader*)gpt->primary_header, | 
 |  100     (GptHeader*)gpt->secondary_header, | 
 |  101   }; | 
 |  102   int i; | 
 |  103  | 
 |  104   for (i = PRIMARY; i <= SECONDARY; ++i) { | 
 |  105     if (headers[i]->reserved || headers[i]->padding) | 
 |  106       INVALIDATE_HEADER(valid_headers, i); | 
 |  107   } | 
 |  108   return valid_headers; | 
 |  109 } | 
 |  110  | 
 |  111 /* my_lba field points to the header itself. | 
 |  112  * So that the my_lba of primary header should be 1 (right after PMBR). | 
 |  113  * The my_lba of secondary header should be the last secotr on drive. */ | 
 |  114 uint32_t CheckMyLba(GptData *gpt) { | 
 |  115   uint32_t valid_headers = MASK_BOTH; | 
 |  116   GptHeader *primary_header, *secondary_header; | 
 |  117  | 
 |  118   primary_header = (GptHeader*)gpt->primary_header; | 
 |  119   secondary_header = (GptHeader*)gpt->secondary_header; | 
 |  120  | 
 |  121   if (primary_header->my_lba != GPT_PMBR_SECTOR)  /* 2nd sector on drive */ | 
 |  122     INVALIDATE_HEADER(valid_headers, PRIMARY); | 
 |  123   if (secondary_header->my_lba != (gpt->drive_sectors - 1))  /* last sector */ | 
 |  124     INVALIDATE_HEADER(valid_headers, SECONDARY); | 
 |  125   return valid_headers; | 
 |  126 } | 
 |  127  | 
 |  128 /* SizeOfPartitionEntry must be between MIN_SIZE_OF_ENTRY and | 
 |  129  * MAX_SIZE_OF_ENTRY, and a multiple of SIZE_OF_ENTRY_MULTIPLE. */ | 
 |  130 uint32_t CheckSizeOfPartitionEntry(GptData *gpt) { | 
 |  131   uint32_t valid_headers = MASK_BOTH; | 
 |  132   GptHeader *headers[] = { | 
 |  133     (GptHeader*)gpt->primary_header, | 
 |  134     (GptHeader*)gpt->secondary_header, | 
 |  135   }; | 
 |  136   int i; | 
 |  137  | 
 |  138   for (i = PRIMARY; i <= SECONDARY; ++i) { | 
 |  139     uint32_t size_of_entry = headers[i]->size_of_entry; | 
 |  140     if ((size_of_entry < MIN_SIZE_OF_ENTRY) || | 
 |  141         (size_of_entry > MAX_SIZE_OF_ENTRY) || | 
 |  142         (size_of_entry & (SIZE_OF_ENTRY_MULTIPLE - 1))) | 
 |  143       INVALIDATE_HEADER(valid_headers, i); | 
 |  144   } | 
 |  145   return valid_headers; | 
 |  146 } | 
 |  147  | 
 |  148 /* number_of_entries must be between MIN_NUMBER_OF_ENTRIES and | 
 |  149  * MAX_NUMBER_OF_ENTRIES, and size_of_entry * number_of_entries must be | 
 |  150  * equal to TOTAL_ENTRIES_SIZE. */ | 
 |  151 uint32_t CheckNumberOfEntries(GptData *gpt) { | 
 |  152   uint32_t valid_headers = MASK_BOTH; | 
 |  153   GptHeader *headers[] = { | 
 |  154     (GptHeader*)gpt->primary_header, | 
 |  155     (GptHeader*)gpt->secondary_header, | 
 |  156   }; | 
 |  157   int i; | 
 |  158  | 
 |  159   for (i = PRIMARY; i <= SECONDARY; ++i) { | 
 |  160     uint32_t number_of_entries = headers[i]->number_of_entries; | 
 |  161     if ((number_of_entries < MIN_NUMBER_OF_ENTRIES) || | 
 |  162         (number_of_entries > MAX_NUMBER_OF_ENTRIES) || | 
 |  163         (number_of_entries * headers[i]->size_of_entry != TOTAL_ENTRIES_SIZE)) | 
 |  164       INVALIDATE_HEADER(valid_headers, i); | 
 |  165   } | 
 |  166   return valid_headers; | 
 |  167 } | 
 |  168  | 
 |  169 /* Make sure entries_lba is correct. | 
 |  170  *   2 for primary entries | 
 |  171  *   drive_sectors-1-GPT_ENTRIES_SECTORS for secondary entries. */ | 
 |  172 uint32_t CheckEntriesLba(GptData *gpt) { | 
 |  173   uint32_t valid_headers = MASK_BOTH; | 
 |  174   GptHeader *primary_header, *secondary_header; | 
 |  175  | 
 |  176   primary_header = (GptHeader*)gpt->primary_header; | 
 |  177   secondary_header = (GptHeader*)gpt->secondary_header; | 
 |  178  | 
 |  179   /* We assume the primary partition entry table is located at the sector | 
 |  180    * right after primary partition header. */ | 
 |  181   if (primary_header->entries_lba != (GPT_PMBR_SECTOR + GPT_HEADER_SECTOR)) | 
 |  182     INVALIDATE_HEADER(valid_headers, PRIMARY); | 
 |  183   /* We assume the secondary partition entry table is the 32 sectors | 
 |  184    * right before the secondary partition header. */ | 
 |  185   if (secondary_header->entries_lba != | 
 |  186       (gpt->drive_sectors - 1 - GPT_ENTRIES_SECTORS)) | 
 |  187     INVALIDATE_HEADER(valid_headers, SECONDARY); | 
 |  188   return valid_headers; | 
 |  189 } | 
 |  190  | 
 |  191 /* FirstUsableLBA must be after the end of the primary GPT table array. | 
 |  192  * LastUsableLBA must be before the start of the secondary GPT table array. | 
 |  193  * FirstUsableLBA <= LastUsableLBA. */ | 
 |  194 uint32_t CheckValidUsableLbas(GptData *gpt) { | 
 |  195   uint32_t valid_headers = MASK_BOTH; | 
 |  196   uint64_t end_of_primary_entries; | 
 |  197   uint64_t start_of_secondary_entries; | 
 |  198   GptHeader *headers[] = { | 
 |  199     (GptHeader*)gpt->primary_header, | 
 |  200     (GptHeader*)gpt->secondary_header, | 
 |  201   }; | 
 |  202   int i; | 
 |  203  | 
 |  204   end_of_primary_entries = GPT_PMBR_SECTOR + GPT_HEADER_SECTOR + | 
 |  205                            GPT_ENTRIES_SECTORS; | 
 |  206   start_of_secondary_entries = (gpt->drive_sectors - 1 - GPT_ENTRIES_SECTORS); | 
 |  207  | 
 |  208   for (i = PRIMARY; i <= SECONDARY; ++i) { | 
 |  209     if (headers[i]->first_usable_lba < end_of_primary_entries) | 
 |  210       INVALIDATE_HEADER(valid_headers, i); | 
 |  211     if (headers[i]->last_usable_lba >= start_of_secondary_entries) | 
 |  212       INVALIDATE_HEADER(valid_headers, i); | 
 |  213     if (headers[i]->first_usable_lba > headers[i]->last_usable_lba) | 
 |  214       INVALIDATE_HEADER(valid_headers, i); | 
 |  215   } | 
 |  216  | 
 |  217   if (headers[PRIMARY]->first_usable_lba - headers[PRIMARY]->entries_lba < | 
 |  218       GPT_ENTRIES_SECTORS) | 
 |  219     INVALIDATE_HEADER(valid_headers, PRIMARY); | 
 |  220   if (headers[SECONDARY]->last_usable_lba >= headers[SECONDARY]->entries_lba) | 
 |  221     INVALIDATE_HEADER(valid_headers, SECONDARY); | 
 |  222  | 
 |  223   return valid_headers; | 
 |  224 } | 
 |  225  | 
 |  226 /* Checks header CRC */ | 
 |  227 uint32_t CheckHeaderCrc(GptData *gpt) { | 
 |  228   uint32_t crc32, original_crc32; | 
 |  229   uint32_t valid_headers = MASK_BOTH; | 
 |  230   GptHeader *headers[] = { | 
 |  231     (GptHeader*)gpt->primary_header, | 
 |  232     (GptHeader*)gpt->secondary_header, | 
 |  233   }; | 
 |  234   int i; | 
 |  235  | 
 |  236   for (i = PRIMARY; i <= SECONDARY; ++i) { | 
 |  237     original_crc32 = headers[i]->header_crc32; | 
 |  238     headers[i]->header_crc32 = 0; | 
 |  239     crc32 = Crc32((const uint8_t *)headers[i], headers[i]->size); | 
 |  240     headers[i]->header_crc32 = original_crc32; | 
 |  241     if (crc32 != original_crc32) | 
 |  242       INVALIDATE_HEADER(valid_headers, i); | 
 |  243   } | 
 |  244   return valid_headers; | 
 |  245 } | 
 |  246  | 
 |  247 /* Checks entries CRC */ | 
 |  248 uint32_t CheckEntriesCrc(GptData *gpt) { | 
 |  249   uint32_t crc32; | 
 |  250   uint32_t valid_entries = MASK_BOTH; | 
 |  251   GptHeader *headers[] = { | 
 |  252     (GptHeader*)gpt->primary_header, | 
 |  253     (GptHeader*)gpt->secondary_header, | 
 |  254   }; | 
 |  255   GptEntry *entries[] = { | 
 |  256     (GptEntry*)gpt->primary_entries, | 
 |  257     (GptEntry*)gpt->secondary_entries, | 
 |  258   }; | 
 |  259   int i; | 
 |  260  | 
 |  261   for (i = PRIMARY; i <= SECONDARY; ++i) { | 
 |  262     crc32 = Crc32((const uint8_t *)entries[i], TOTAL_ENTRIES_SIZE); | 
 |  263     if (crc32 != headers[i]->entries_crc32) | 
 |  264       INVALIDATE_HEADER(valid_entries, i); | 
 |  265   } | 
 |  266   return valid_entries; | 
 |  267 } | 
 |  268  | 
 |  269 /* Returns non-zero if the given GUID is non-zero. */ | 
 |  270 static int NonZeroGuid(const Guid *guid) { | 
 |  271   static Guid zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}}; | 
 |  272   return Memcmp(&zero, guid, sizeof(zero)); | 
 |  273 } | 
 |  274  | 
 |  275 /* Checks if entries geometry is valid. | 
 |  276  * All active (non-zero PartitionTypeGUID) partition entries should have: | 
 |  277  *   entry.StartingLBA >= header.FirstUsableLBA | 
 |  278  *   entry.EndingLBA <= header.LastUsableLBA | 
 |  279  *   entry.StartingLBA <= entry.EndingLBA | 
 |  280  */ | 
 |  281 uint32_t CheckValidEntries(GptData *gpt) { | 
 |  282   uint32_t valid_entries = MASK_BOTH; | 
 |  283   GptHeader *headers[] = { | 
 |  284     (GptHeader*)gpt->primary_header, | 
 |  285     (GptHeader*)gpt->secondary_header, | 
 |  286   }; | 
 |  287   GptEntry *entries[] = { | 
 |  288     (GptEntry*)gpt->primary_entries, | 
 |  289     (GptEntry*)gpt->secondary_entries, | 
 |  290   }; | 
 |  291   int copy, entry_index; | 
 |  292   GptEntry *entry; | 
 |  293  | 
 |  294   for (copy = PRIMARY; copy <= SECONDARY; ++copy) { | 
 |  295     for (entry_index = 0; | 
 |  296          entry_index < headers[copy]->number_of_entries; | 
 |  297          ++entry_index) { | 
 |  298       entry = (GptEntry*)&(((uint8_t*)entries[copy]) | 
 |  299           [entry_index * headers[copy]->size_of_entry]); | 
 |  300       if (NonZeroGuid(&entry->type)) { | 
 |  301         if ((entry->starting_lba < headers[copy]->first_usable_lba) || | 
 |  302             (entry->ending_lba > headers[copy]->last_usable_lba) || | 
 |  303             (entry->ending_lba < entry->starting_lba)) | 
 |  304           INVALIDATE_HEADER(valid_entries, copy); | 
 |  305       } | 
 |  306     } | 
 |  307   } | 
 |  308   return valid_entries; | 
 |  309 } | 
 |  310  | 
 |  311 static pair_t pairs[MAX_NUMBER_OF_ENTRIES]; | 
 |  312 /* Callback function for QuickSort(). Returns 1 if 'a_' should precede 'b_'. */ | 
 |  313 int compare_pair(const void *a_, const void *b_) { | 
 |  314   const pair_t *a = a_; | 
 |  315   const pair_t *b = b_; | 
 |  316   if (a->starting <= b->starting) return 1; | 
 |  317   return 0; | 
 |  318 } | 
 |  319  | 
 |  320 /* First sorts by starting_lba, and traverse everyone once if its starting_lba | 
 |  321  * is between previous starting_lba and ending_lba. If yes, overlapped. | 
 |  322  * Returns 1 if overlap is found. */ | 
 |  323 int OverlappedEntries(GptEntry *entries, uint32_t number_of_entries) { | 
 |  324   int i, num_of_pair = 0; | 
 |  325   for (i = 0; i < number_of_entries; ++i) { | 
 |  326     if (NonZeroGuid(&entries[i].type)) { | 
 |  327       pairs[num_of_pair].starting = entries[i].starting_lba; | 
 |  328       pairs[num_of_pair].ending = entries[i].ending_lba; | 
 |  329       ++num_of_pair; | 
 |  330     } | 
 |  331   } | 
 |  332   QuickSort(&pairs, num_of_pair, sizeof(pair_t), compare_pair); | 
 |  333  | 
 |  334   for (i = 1; i < num_of_pair; ++i) { | 
 |  335     if ((pairs[i].starting >= pairs[i-1].starting) && | 
 |  336         (pairs[i].starting <= pairs[i-1].ending)) | 
 |  337       return 1; | 
 |  338   } | 
 |  339  | 
 |  340   return 0; | 
 |  341 } | 
 |  342  | 
 |  343 /* Checks if any two partitions are overlapped in primary and secondary entries. | 
 |  344  */ | 
 |  345 uint32_t CheckOverlappedPartition(GptData *gpt) { | 
 |  346   uint32_t valid_entries = MASK_BOTH; | 
 |  347   GptHeader *headers[] = { | 
 |  348     (GptHeader*)gpt->primary_header, | 
 |  349     (GptHeader*)gpt->secondary_header, | 
 |  350   }; | 
 |  351   GptEntry *entries[] = { | 
 |  352     (GptEntry*)gpt->primary_entries, | 
 |  353     (GptEntry*)gpt->secondary_entries, | 
 |  354   }; | 
 |  355   int i; | 
 |  356  | 
 |  357   for (i = PRIMARY; i <= SECONDARY; ++i) { | 
 |  358     if (OverlappedEntries(entries[i], headers[i]->number_of_entries)) | 
 |  359       INVALIDATE_ENTRIES(valid_entries, i); | 
 |  360   } | 
 |  361   return valid_entries; | 
 |  362 } | 
 |  363  | 
 |  364 /* Primary entries and secondary entries should be bitwise identical. | 
 |  365  * If two entries tables are valid, compare them. If not the same, | 
 |  366  * overwrites secondary with primary (primary always has higher priority), | 
 |  367  * and marks secondary as modified. | 
 |  368  * If only one is valid, overwrites invalid one. | 
 |  369  * If all are invalid, does nothing. | 
 |  370  * This function returns bit masks for GptData.modified field. */ | 
 |  371 uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries) { | 
 |  372   if (valid_entries == MASK_BOTH) { | 
 |  373     if (Memcmp(gpt->primary_entries, gpt->secondary_entries, | 
 |  374                TOTAL_ENTRIES_SIZE)) { | 
 |  375       Memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE); | 
 |  376       return GPT_MODIFIED_ENTRIES2; | 
 |  377     } | 
 |  378   } else if (valid_entries == MASK_PRIMARY) { | 
 |  379     Memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE); | 
 |  380     return GPT_MODIFIED_ENTRIES2; | 
 |  381   } else if (valid_entries == MASK_SECONDARY) { | 
 |  382     Memcpy(gpt->primary_entries, gpt->secondary_entries, TOTAL_ENTRIES_SIZE); | 
 |  383     return GPT_MODIFIED_ENTRIES1; | 
 |  384   } | 
 |  385  | 
 |  386   return 0; | 
 |  387 } | 
 |  388  | 
 |  389 /* Two headers are NOT bitwise identical. For example, my_lba pointers to header | 
 |  390  * itself so that my_lba in primary and secondary is definitely different. | 
 |  391  * Only the following fields should be identical. | 
 |  392  * | 
 |  393  *   first_usable_lba | 
 |  394  *   last_usable_lba | 
 |  395  *   number_of_entries | 
 |  396  *   size_of_entry | 
 |  397  *   disk_uuid | 
 |  398  * | 
 |  399  * If any of above field are not matched, overwrite secondary with primary since | 
 |  400  * we always trust primary. | 
 |  401  * If any one of header is invalid, copy from another. */ | 
 |  402 int IsSynonymous(const GptHeader* a, const GptHeader* b) { | 
 |  403   if ((a->first_usable_lba == b->first_usable_lba) && | 
 |  404       (a->last_usable_lba == b->last_usable_lba) && | 
 |  405       (a->number_of_entries == b->number_of_entries) && | 
 |  406       (a->size_of_entry == b->size_of_entry) && | 
 |  407       (!Memcmp(&a->disk_uuid, &b->disk_uuid, sizeof(Guid)))) | 
 |  408     return 1; | 
 |  409   return 0; | 
 |  410 } | 
 |  411  | 
 |  412 /* The above five fields are shared between primary and secondary headers. | 
 |  413  * We can recover one header from another through copying those fields. */ | 
 |  414 void CopySynonymousParts(GptHeader* target, const GptHeader* source) { | 
 |  415   target->first_usable_lba = source->first_usable_lba; | 
 |  416   target->last_usable_lba = source->last_usable_lba; | 
 |  417   target->number_of_entries = source->number_of_entries; | 
 |  418   target->size_of_entry = source->size_of_entry; | 
 |  419   Memcpy(&target->disk_uuid, &source->disk_uuid, sizeof(Guid)); | 
 |  420 } | 
 |  421  | 
 |  422 /* This function repairs primary and secondary headers if possible. | 
 |  423  * If both headers are valid (CRC32 is correct) but | 
 |  424  *   a) indicate inconsistent usable LBA ranges, | 
 |  425  *   b) inconsistent partition entry size and number, | 
 |  426  *   c) inconsistent disk_uuid, | 
 |  427  * we will use the primary header to overwrite secondary header. | 
 |  428  * If primary is invalid (CRC32 is wrong), then we repair it from secondary. | 
 |  429  * If secondary is invalid (CRC32 is wrong), then we repair it from primary. | 
 |  430  * This function returns the bitmasks for modified header. | 
 |  431  * Note that CRC value is not re-computed in this function. UpdateCrc() will | 
 |  432  * do it later. | 
 |  433  */ | 
 |  434 uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers) { | 
 |  435   GptHeader *primary_header, *secondary_header; | 
 |  436  | 
 |  437   primary_header = (GptHeader*)gpt->primary_header; | 
 |  438   secondary_header = (GptHeader*)gpt->secondary_header; | 
 |  439  | 
 |  440   if (valid_headers == MASK_BOTH) { | 
 |  441     if (!IsSynonymous(primary_header, secondary_header)) { | 
 |  442       CopySynonymousParts(secondary_header, primary_header); | 
 |  443       return GPT_MODIFIED_HEADER2; | 
 |  444     } | 
 |  445   } else if (valid_headers == MASK_PRIMARY) { | 
 |  446     Memcpy(secondary_header, primary_header, primary_header->size); | 
 |  447     secondary_header->my_lba = gpt->drive_sectors - 1;  /* the last sector */ | 
 |  448     secondary_header->entries_lba = secondary_header->my_lba - | 
 |  449                                     GPT_ENTRIES_SECTORS; | 
 |  450     return GPT_MODIFIED_HEADER2; | 
 |  451   } else if (valid_headers == MASK_SECONDARY) { | 
 |  452     Memcpy(primary_header, secondary_header, secondary_header->size); | 
 |  453     primary_header->my_lba = GPT_PMBR_SECTOR;  /* the second sector on drive */ | 
 |  454     primary_header->entries_lba = primary_header->my_lba + GPT_HEADER_SECTOR; | 
 |  455     return GPT_MODIFIED_HEADER1; | 
 |  456   } | 
 |  457  | 
 |  458   return 0; | 
 |  459 } | 
 |  460  | 
 |  461 /*  Update CRC value if necessary.  */ | 
 |  462 void UpdateCrc(GptData *gpt) { | 
 |  463   GptHeader *primary_header, *secondary_header; | 
 |  464  | 
 |  465   primary_header = (GptHeader*)gpt->primary_header; | 
 |  466   secondary_header = (GptHeader*)gpt->secondary_header; | 
 |  467  | 
 |  468   if (gpt->modified & GPT_MODIFIED_HEADER1) { | 
 |  469     primary_header->header_crc32 = 0; | 
 |  470     primary_header->header_crc32 = Crc32( | 
 |  471         (const uint8_t *)primary_header, primary_header->size); | 
 |  472   } | 
 |  473   if (gpt->modified & GPT_MODIFIED_HEADER2) { | 
 |  474     secondary_header->header_crc32 = 0; | 
 |  475     secondary_header->header_crc32 = Crc32( | 
 |  476         (const uint8_t *)secondary_header, secondary_header->size); | 
 |  477   } | 
 |  478   if (gpt->modified & GPT_MODIFIED_ENTRIES1) { | 
 |  479     primary_header->entries_crc32 = | 
 |  480         Crc32(gpt->primary_entries, TOTAL_ENTRIES_SIZE); | 
 |  481   } | 
 |  482   if (gpt->modified & GPT_MODIFIED_ENTRIES2) { | 
 |  483     secondary_header->entries_crc32 = | 
 |  484         Crc32(gpt->secondary_entries, TOTAL_ENTRIES_SIZE); | 
 |  485   } | 
 |  486 } | 
 |  487  | 
 |  488 /* Does every sanity check, and returns if any header/entries needs to be | 
 |  489  * written back. */ | 
 |  490 int GptInit(GptData *gpt) { | 
 |  491   uint32_t valid_headers = MASK_BOTH; | 
 |  492   uint32_t valid_entries = MASK_BOTH; | 
 |  493   int retval; | 
 |  494  | 
 |  495   retval = CheckParameters(gpt); | 
 |  496   if (retval != GPT_SUCCESS) | 
 |  497     return retval; | 
 |  498  | 
 |  499   /* Initialize values */ | 
 |  500   gpt->modified = 0; | 
 |  501  | 
 |  502   /* Start checking if header parameters are valid. */ | 
 |  503   valid_headers &= CheckHeaderSignature(gpt); | 
 |  504   valid_headers &= CheckRevision(gpt); | 
 |  505   valid_headers &= CheckSize(gpt); | 
 |  506   valid_headers &= CheckReservedFields(gpt); | 
 |  507   valid_headers &= CheckMyLba(gpt); | 
 |  508   valid_headers &= CheckSizeOfPartitionEntry(gpt); | 
 |  509   valid_headers &= CheckNumberOfEntries(gpt); | 
 |  510   valid_headers &= CheckEntriesLba(gpt); | 
 |  511   valid_headers &= CheckValidUsableLbas(gpt); | 
 |  512  | 
 |  513   /* Checks if headers are valid. */ | 
 |  514   valid_headers &= CheckHeaderCrc(gpt); | 
 |  515   gpt->modified |= RepairHeader(gpt, valid_headers); | 
 |  516  | 
 |  517   /* Checks if entries are valid. */ | 
 |  518   valid_entries &= CheckEntriesCrc(gpt); | 
 |  519   valid_entries &= CheckValidEntries(gpt); | 
 |  520   valid_entries &= CheckOverlappedPartition(gpt); | 
 |  521   gpt->modified |= RepairEntries(gpt, valid_entries); | 
 |  522  | 
 |  523   /* Returns error if we don't have any valid header/entries to use. */ | 
 |  524   if (!valid_headers) | 
 |  525     return GPT_ERROR_INVALID_HEADERS; | 
 |  526   if (!valid_entries) | 
 |  527     return GPT_ERROR_INVALID_ENTRIES; | 
 |  528  | 
 |  529   UpdateCrc(gpt); | 
 |  530  | 
 |  531   /* FIXME: will remove the next line soon. */ | 
 |  532   gpt->current_kernel = 1; | 
 |  533   return GPT_SUCCESS; | 
 |  534 } | 
 |  535  | 
|   11 /* stub code */ |  536 /* stub code */ | 
|   12 static int start[] = { 34, 10034 }; |  537 static int start[] = { 34, 10034 }; | 
|   13  |  538  | 
|   14 int GptInit(GptData_t *gpt) { |  539 int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size) { | 
|   15   int valid_headers[2] = {1, 1}; |  | 
|   16  |  | 
|   17   /* check header signature */ |  | 
|   18   if (Memcmp(gpt->primary_header, GPT_HEADER_SIGNATURE, |  | 
|   19                                   GPT_HEADER_SIGNATURE_SIZE)) |  | 
|   20     valid_headers[0] = 0; |  | 
|   21   if (Memcmp(gpt->secondary_header, GPT_HEADER_SIGNATURE, |  | 
|   22                                   GPT_HEADER_SIGNATURE_SIZE)) |  | 
|   23     valid_headers[1] = 0; |  | 
|   24  |  | 
|   25   if (!valid_headers[0] && !valid_headers[1]) |  | 
|   26     return GPT_ERROR_INVALID_HEADERS; |  | 
|   27  |  | 
|   28   gpt->current_kernel = 1; |  | 
|   29   return GPT_SUCCESS; |  | 
|   30 } |  | 
|   31  |  | 
|   32 int GptNextKernelEntry(GptData_t *gpt, uint64_t *start_sector, uint64_t *size) { |  | 
|   33   /* FIXME: the following code is not really code, just returns anything */ |  540   /* FIXME: the following code is not really code, just returns anything */ | 
|   34   gpt->current_kernel ^= 1; |  541   gpt->current_kernel ^= 1; | 
|   35   if (start_sector) *start_sector = start[gpt->current_kernel]; |  542   if (start_sector) *start_sector = start[gpt->current_kernel]; | 
|   36   if (size) *size = 10000; |  543   if (size) *size = 10000; | 
|   37   return GPT_SUCCESS; |  544   return GPT_SUCCESS; | 
|   38 } |  545 } | 
|   39  |  546  | 
|   40 int GptUpdateKernelEntry(GptData_t *gpt, uint32_t update_type) { |  547 int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type) { | 
|   41   /* FIXME: the following code is not really code, just return anything */ |  548   /* FIXME: the following code is not really code, just return anything */ | 
|   42   gpt->modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) << |  549   gpt->modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) << | 
|   43                    gpt->current_kernel; |  550                    gpt->current_kernel; | 
|   44   return GPT_SUCCESS; |  551   return GPT_SUCCESS; | 
|   45 } |  552 } | 
| OLD | NEW |