mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 02:05:01 +00:00
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>
This commit is contained in:
@@ -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 = \
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
42
cgpt/cgpt_legacy.c
Normal file
42
cgpt/cgpt_legacy.c
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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_
|
||||
|
||||
67
cgpt/cmd_legacy.c
Normal file
67
cgpt/cmd_legacy.c
Normal file
@@ -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);
|
||||
}
|
||||
@@ -45,7 +45,8 @@ int CheckHeader(GptHeader *h, int is_secondary, uint64_t drive_sectors) {
|
||||
|
||||
/* Make sure we're looking at a header of reasonable size before
|
||||
* attempting to calculate CRC. */
|
||||
if (Memcmp(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE))
|
||||
if (Memcmp(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE) &&
|
||||
Memcmp(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE))
|
||||
return 1;
|
||||
if (h->revision != GPT_HEADER_REVISION)
|
||||
return 1;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
__pragma(pack(push,1)) /* Support packing for MSVC. */
|
||||
|
||||
#define GPT_HEADER_SIGNATURE "EFI PART"
|
||||
#define GPT_HEADER_SIGNATURE2 "CHROMEOS"
|
||||
#define GPT_HEADER_SIGNATURE_SIZE sizeof(GPT_HEADER_SIGNATURE)
|
||||
#define GPT_HEADER_REVISION 0x00010000
|
||||
|
||||
|
||||
@@ -72,24 +72,36 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) {
|
||||
* Returns 0 if successful, 1 if error. */
|
||||
int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) {
|
||||
|
||||
int legacy = 0;
|
||||
uint64_t entries_sectors = TOTAL_ENTRIES_SIZE / gptdata->sector_bytes;
|
||||
|
||||
if (gptdata->primary_header) {
|
||||
GptHeader* h = (GptHeader*)(gptdata->primary_header);
|
||||
legacy = !Memcmp(h->signature, GPT_HEADER_SIGNATURE2,
|
||||
GPT_HEADER_SIGNATURE_SIZE);
|
||||
if (gptdata->modified & GPT_MODIFIED_HEADER1) {
|
||||
if (legacy) {
|
||||
VBDEBUG(("Not updating GPT header 1: legacy mode is enabled.\n"));
|
||||
} else {
|
||||
VBDEBUG(("Updating GPT header 1\n"));
|
||||
if (0 != VbExDiskWrite(disk_handle, 1, 1, gptdata->primary_header))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
VbExFree(gptdata->primary_header);
|
||||
}
|
||||
|
||||
if (gptdata->primary_entries) {
|
||||
if (gptdata->modified & GPT_MODIFIED_ENTRIES1) {
|
||||
if (legacy) {
|
||||
VBDEBUG(("Not updating GPT entries 1: legacy mode is enabled.\n"));
|
||||
} else {
|
||||
VBDEBUG(("Updating GPT entries 1\n"));
|
||||
if (0 != VbExDiskWrite(disk_handle, 2, entries_sectors,
|
||||
gptdata->primary_entries))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
VbExFree(gptdata->primary_entries);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user