aboutsummaryrefslogtreecommitdiff
path: root/cgpt
diff options
context:
space:
mode:
authorStefan Reinauer <reinauer@chromium.org>2012-08-23 15:06:25 -0700
committerGerrit <chrome-bot@google.com>2012-09-19 15:33:30 -0700
commitb7b865cfee68190babd971ab9a897bdabbab075f (patch)
tree8ad900ddff6a69f9a65cd0507857a6da2677592f /cgpt
parent40d8651bb36048c9b5f07be97ff17b2cf503015e (diff)
downloadvboot_reference-b7b865cfee68190babd971ab9a897bdabbab075f.tar.gz
Support alternative GPT header signature
In order to dual boot Windows and ChromeOS, Windows must not find a GPT partition table on the disk. So change ChromeOS to cope with an alternative signature "CHROMEOS" instead of the standard "EFI PART" BUG=chrome-os-partner:6108 TEST=rebuild chromeos, install it, run cgpt legacy /dev/sda dd if=/dev/sda of=/tmp/x bs=1k hexdump -C /tmp/X see the string CHROMEOS BRANCH=link Signed-off-by: Stefan Reinauer <reinauer@chromium.org> Change-Id: Ia88eff33b9880bd73a78c1b8e026c1f8298c4557 Reviewed-on: https://gerrit.chromium.org/gerrit/31264 Reviewed-by: Randall Spangler <rspangler@chromium.org> Commit-Ready: Stefan Reinauer <reinauer@chromium.org> Tested-by: Stefan Reinauer <reinauer@chromium.org>
Diffstat (limited to 'cgpt')
-rw-r--r--cgpt/Makefile2
-rw-r--r--cgpt/cgpt.c1
-rw-r--r--cgpt/cgpt.h1
-rw-r--r--cgpt/cgpt_common.c12
-rw-r--r--cgpt/cgpt_legacy.c42
-rw-r--r--cgpt/cgpt_params.h9
-rw-r--r--cgpt/cmd_legacy.c67
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(&params, 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(&params);
+}