diff options
Diffstat (limited to 'cgpt')
-rw-r--r-- | cgpt/Makefile | 2 | ||||
-rw-r--r-- | cgpt/cgpt.c | 1 | ||||
-rw-r--r-- | cgpt/cgpt.h | 1 | ||||
-rw-r--r-- | cgpt/cgpt_common.c | 12 | ||||
-rw-r--r-- | cgpt/cgpt_legacy.c | 42 | ||||
-rw-r--r-- | cgpt/cgpt_params.h | 9 | ||||
-rw-r--r-- | cgpt/cmd_legacy.c | 67 |
7 files changed, 133 insertions, 1 deletions
diff --git a/cgpt/Makefile b/cgpt/Makefile index 8e810d42..c22a680c 100644 --- a/cgpt/Makefile +++ b/cgpt/Makefile @@ -24,6 +24,7 @@ ALL_SRCS = \ cgpt_repair.c \ cgpt_prioritize.c \ cgpt_find.c \ + cgpt_legacy.c \ cmd_show.c \ cmd_repair.c \ cmd_create.c \ @@ -31,6 +32,7 @@ ALL_SRCS = \ cmd_boot.c \ cmd_find.c \ cmd_prioritize.c \ + cmd_legacy.c \ cgpt_common.c LIB_CGPT_CC_SRCS = \ diff --git a/cgpt/cgpt.c b/cgpt/cgpt.c index e963142a..ac7aecdd 100644 --- a/cgpt/cgpt.c +++ b/cgpt/cgpt.c @@ -30,6 +30,7 @@ struct { {"find", cmd_find, "Locate a partition by its GUID"}, {"prioritize", cmd_prioritize, "Reorder the priority of all kernel partitions"}, + {"legacy", cmd_legacy, "Switch between GPT and Legacy GPT"}, }; void Usage(void) { diff --git a/cgpt/cgpt.h b/cgpt/cgpt.h index 6851ded7..b3f7ff3b 100644 --- a/cgpt/cgpt.h +++ b/cgpt/cgpt.h @@ -154,6 +154,7 @@ int cmd_add(int argc, char *argv[]); int cmd_boot(int argc, char *argv[]); int cmd_find(int argc, char *argv[]); int cmd_prioritize(int argc, char *argv[]); +int cmd_legacy(int argc, char *argv[]); #define ARRAY_COUNT(array) (sizeof(array)/sizeof((array)[0])) const char *GptError(int errnum); diff --git a/cgpt/cgpt_common.c b/cgpt/cgpt_common.c index d69eb670..193f2e1e 100644 --- a/cgpt/cgpt_common.c +++ b/cgpt/cgpt_common.c @@ -733,7 +733,9 @@ void UpdateCrc(GptData *gpt) { primary_header = (GptHeader*)gpt->primary_header; secondary_header = (GptHeader*)gpt->secondary_header; - if (gpt->modified & GPT_MODIFIED_ENTRIES1) { + if (gpt->modified & GPT_MODIFIED_ENTRIES1 && + memcmp(primary_header, GPT_HEADER_SIGNATURE2, + GPT_HEADER_SIGNATURE_SIZE)) { primary_header->entries_crc32 = Crc32(gpt->primary_entries, TOTAL_ENTRIES_SIZE); } @@ -785,6 +787,14 @@ int IsSynonymous(const GptHeader* a, const GptHeader* b) { * Note that CRC is NOT re-computed in this function. */ uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries) { + /* If we have an alternate GPT header signature, don't overwrite + * the secondary GPT with the primary one as that might wipe the + * partition table. Also don't overwrite the primary one with the + * secondary one as that will stop Windows from booting. */ + GptHeader* h = (GptHeader*)(gpt->primary_header); + if (!memcmp(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE)) + return 0; + if (valid_entries == MASK_BOTH) { if (memcmp(gpt->primary_entries, gpt->secondary_entries, TOTAL_ENTRIES_SIZE)) { diff --git a/cgpt/cgpt_legacy.c b/cgpt/cgpt_legacy.c new file mode 100644 index 00000000..7d1eeeac --- /dev/null +++ b/cgpt/cgpt_legacy.c @@ -0,0 +1,42 @@ +// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cgpt.h" + +#include <string.h> + +#include "cgptlib_internal.h" +#include "cgpt_params.h" + +int cgpt_legacy(CgptLegacyParams *params) { + struct drive drive; + GptHeader *h1, *h2; + + if (params == NULL) + return CGPT_FAILED; + + if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR)) + return CGPT_FAILED; + + h1 = (GptHeader *)drive.gpt.primary_header; + h2 = (GptHeader *)drive.gpt.secondary_header; + if (params->efipart) { + memcpy(h1->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE); + memcpy(h2->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE); + RepairEntries(&drive.gpt, MASK_SECONDARY); + drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | + GPT_MODIFIED_HEADER2); + } else { + memcpy(h1->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE); + memcpy(h2->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE); + memset(drive.gpt.primary_entries, 0, drive.gpt.sector_bytes); + drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | + GPT_MODIFIED_HEADER2); + } + + UpdateCrc(&drive.gpt); + + // Write it all out + return DriveClose(&drive, 1); +} diff --git a/cgpt/cgpt_params.h b/cgpt/cgpt_params.h index 22af9626..fcee03c4 100644 --- a/cgpt/cgpt_params.h +++ b/cgpt/cgpt_params.h @@ -92,6 +92,11 @@ typedef struct CgptFindParams { int match_partnum; // 0 for no match, 1-N for match } CgptFindParams; +typedef struct CgptLegacyParams { + char *drive_name; + int efipart; +} CgptLegacyParams; + // create related methods. int cgpt_create(CgptCreateParams *params); @@ -116,4 +121,8 @@ int cgpt_prioritize(CgptPrioritizeParams *params); // find related methods. void cgpt_find(CgptFindParams *params); + +// legacy related methods. +int cgpt_legacy(CgptLegacyParams *params); + #endif // VBOOT_REFERENCE_CGPT_CGPT_PARAMS_H_ diff --git a/cgpt/cmd_legacy.c b/cgpt/cmd_legacy.c new file mode 100644 index 00000000..5dad01e3 --- /dev/null +++ b/cgpt/cmd_legacy.c @@ -0,0 +1,67 @@ +// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cgpt.h" + +#include <getopt.h> +#include <string.h> + +#include "cgpt_params.h" + +static void Usage(void) +{ + printf("\nUsage: %s legacy [OPTIONS] DRIVE\n\n" + "Switch GPT header signature to \"CHROMEOS\".\n\n" + "Options:\n" + " -e Switch GPT header signature back to \"EFI PART\"\n" + "\n", progname); +} + +int cmd_legacy(int argc, char *argv[]) { + CgptLegacyParams params; + memset(¶ms, 0, sizeof(params)); + + int c; + int errorcnt = 0; + + opterr = 0; // quiet, you + while ((c=getopt(argc, argv, ":he")) != -1) + { + switch (c) + { + case 'e': + params.efipart = 1; + break; + + case 'h': + Usage(); + return CGPT_OK; + case '?': + Error("unrecognized option: -%c\n", optopt); + errorcnt++; + break; + case ':': + Error("missing argument to -%c\n", optopt); + errorcnt++; + break; + default: + errorcnt++; + break; + } + } + if (errorcnt) + { + Usage(); + return CGPT_FAILED; + } + + if (optind >= argc) { + Usage(); + return CGPT_FAILED; + } + + params.drive_name = argv[optind]; + + return cgpt_legacy(¶ms); +} |