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_repair.c \
|
||||||
cgpt_prioritize.c \
|
cgpt_prioritize.c \
|
||||||
cgpt_find.c \
|
cgpt_find.c \
|
||||||
|
cgpt_legacy.c \
|
||||||
cmd_show.c \
|
cmd_show.c \
|
||||||
cmd_repair.c \
|
cmd_repair.c \
|
||||||
cmd_create.c \
|
cmd_create.c \
|
||||||
@@ -31,6 +32,7 @@ ALL_SRCS = \
|
|||||||
cmd_boot.c \
|
cmd_boot.c \
|
||||||
cmd_find.c \
|
cmd_find.c \
|
||||||
cmd_prioritize.c \
|
cmd_prioritize.c \
|
||||||
|
cmd_legacy.c \
|
||||||
cgpt_common.c
|
cgpt_common.c
|
||||||
|
|
||||||
LIB_CGPT_CC_SRCS = \
|
LIB_CGPT_CC_SRCS = \
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ struct {
|
|||||||
{"find", cmd_find, "Locate a partition by its GUID"},
|
{"find", cmd_find, "Locate a partition by its GUID"},
|
||||||
{"prioritize", cmd_prioritize,
|
{"prioritize", cmd_prioritize,
|
||||||
"Reorder the priority of all kernel partitions"},
|
"Reorder the priority of all kernel partitions"},
|
||||||
|
{"legacy", cmd_legacy, "Switch between GPT and Legacy GPT"},
|
||||||
};
|
};
|
||||||
|
|
||||||
void Usage(void) {
|
void Usage(void) {
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ int cmd_add(int argc, char *argv[]);
|
|||||||
int cmd_boot(int argc, char *argv[]);
|
int cmd_boot(int argc, char *argv[]);
|
||||||
int cmd_find(int argc, char *argv[]);
|
int cmd_find(int argc, char *argv[]);
|
||||||
int cmd_prioritize(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]))
|
#define ARRAY_COUNT(array) (sizeof(array)/sizeof((array)[0]))
|
||||||
const char *GptError(int errnum);
|
const char *GptError(int errnum);
|
||||||
|
|||||||
@@ -733,7 +733,9 @@ void UpdateCrc(GptData *gpt) {
|
|||||||
primary_header = (GptHeader*)gpt->primary_header;
|
primary_header = (GptHeader*)gpt->primary_header;
|
||||||
secondary_header = (GptHeader*)gpt->secondary_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 =
|
primary_header->entries_crc32 =
|
||||||
Crc32(gpt->primary_entries, TOTAL_ENTRIES_SIZE);
|
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.
|
* Note that CRC is NOT re-computed in this function.
|
||||||
*/
|
*/
|
||||||
uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries) {
|
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 (valid_entries == MASK_BOTH) {
|
||||||
if (memcmp(gpt->primary_entries, gpt->secondary_entries,
|
if (memcmp(gpt->primary_entries, gpt->secondary_entries,
|
||||||
TOTAL_ENTRIES_SIZE)) {
|
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
|
int match_partnum; // 0 for no match, 1-N for match
|
||||||
} CgptFindParams;
|
} CgptFindParams;
|
||||||
|
|
||||||
|
typedef struct CgptLegacyParams {
|
||||||
|
char *drive_name;
|
||||||
|
int efipart;
|
||||||
|
} CgptLegacyParams;
|
||||||
|
|
||||||
// create related methods.
|
// create related methods.
|
||||||
int cgpt_create(CgptCreateParams *params);
|
int cgpt_create(CgptCreateParams *params);
|
||||||
|
|
||||||
@@ -116,4 +121,8 @@ int cgpt_prioritize(CgptPrioritizeParams *params);
|
|||||||
|
|
||||||
// find related methods.
|
// find related methods.
|
||||||
void cgpt_find(CgptFindParams *params);
|
void cgpt_find(CgptFindParams *params);
|
||||||
|
|
||||||
|
// legacy related methods.
|
||||||
|
int cgpt_legacy(CgptLegacyParams *params);
|
||||||
|
|
||||||
#endif // VBOOT_REFERENCE_CGPT_CGPT_PARAMS_H_
|
#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
|
/* Make sure we're looking at a header of reasonable size before
|
||||||
* attempting to calculate CRC. */
|
* 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;
|
return 1;
|
||||||
if (h->revision != GPT_HEADER_REVISION)
|
if (h->revision != GPT_HEADER_REVISION)
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
__pragma(pack(push,1)) /* Support packing for MSVC. */
|
__pragma(pack(push,1)) /* Support packing for MSVC. */
|
||||||
|
|
||||||
#define GPT_HEADER_SIGNATURE "EFI PART"
|
#define GPT_HEADER_SIGNATURE "EFI PART"
|
||||||
|
#define GPT_HEADER_SIGNATURE2 "CHROMEOS"
|
||||||
#define GPT_HEADER_SIGNATURE_SIZE sizeof(GPT_HEADER_SIGNATURE)
|
#define GPT_HEADER_SIGNATURE_SIZE sizeof(GPT_HEADER_SIGNATURE)
|
||||||
#define GPT_HEADER_REVISION 0x00010000
|
#define GPT_HEADER_REVISION 0x00010000
|
||||||
|
|
||||||
|
|||||||
@@ -72,24 +72,36 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) {
|
|||||||
* Returns 0 if successful, 1 if error. */
|
* Returns 0 if successful, 1 if error. */
|
||||||
int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) {
|
int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) {
|
||||||
|
|
||||||
|
int legacy = 0;
|
||||||
uint64_t entries_sectors = TOTAL_ENTRIES_SIZE / gptdata->sector_bytes;
|
uint64_t entries_sectors = TOTAL_ENTRIES_SIZE / gptdata->sector_bytes;
|
||||||
|
|
||||||
if (gptdata->primary_header) {
|
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 (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"));
|
VBDEBUG(("Updating GPT header 1\n"));
|
||||||
if (0 != VbExDiskWrite(disk_handle, 1, 1, gptdata->primary_header))
|
if (0 != VbExDiskWrite(disk_handle, 1, 1, gptdata->primary_header))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
VbExFree(gptdata->primary_header);
|
VbExFree(gptdata->primary_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gptdata->primary_entries) {
|
if (gptdata->primary_entries) {
|
||||||
if (gptdata->modified & GPT_MODIFIED_ENTRIES1) {
|
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"));
|
VBDEBUG(("Updating GPT entries 1\n"));
|
||||||
if (0 != VbExDiskWrite(disk_handle, 2, entries_sectors,
|
if (0 != VbExDiskWrite(disk_handle, 2, entries_sectors,
|
||||||
gptdata->primary_entries))
|
gptdata->primary_entries))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
VbExFree(gptdata->primary_entries);
|
VbExFree(gptdata->primary_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user