mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-25 18:55:24 +00:00
cgpt supports dev and add/delete/modify commands.
Review URL: http://codereview.chromium.org/2374001
This commit is contained in:
@@ -10,7 +10,8 @@ LIBS += $(FWLIB)
|
||||
|
||||
all: cgpt
|
||||
|
||||
cgpt: cgpt.o cgpt_attribute.o cgpt_options.o cgpt_repair.o cgpt_show.o $(LIBS)
|
||||
cgpt: cgpt.o cgpt_add_modify_delete.o cgpt_attribute.o cgpt_dev.o \
|
||||
cgpt_options.o cgpt_repair.o cgpt_show.o $(LIBS)
|
||||
$(CC) -o cgpt $(CFLAGS) $^
|
||||
|
||||
.c.o: $(INCLUDES)
|
||||
|
||||
@@ -38,8 +38,12 @@ struct {
|
||||
int (*fp)(int argc, char *argv[]);
|
||||
const char *comment;
|
||||
} cmds[] = {
|
||||
{"add", CgptAdm, "Add a partition to drive"},
|
||||
{"delete", CgptAdm, "Delete a partition on drive"},
|
||||
{"modify", CgptAdm, "Modify the partition on drive"},
|
||||
{"attribute", CgptAttribute, "Update GPT attribute bits "
|
||||
"(for ChromeOS kernel entry only)"},
|
||||
{"dev", CgptDev, "Developper mode"},
|
||||
{"repair", CgptRepair, "Repair primary and secondary headers and tables"},
|
||||
{"show", CgptShow, "Show partition details"},
|
||||
};
|
||||
@@ -51,7 +55,7 @@ void Usage(const char *message) {
|
||||
|
||||
if (message) printf("%s\n", message);
|
||||
printf("Usage: %s COMMAND [OPTIONS]\n\n"
|
||||
"Supported commands:\n\n",
|
||||
"Supported COMMANDs:\n\n",
|
||||
progname);
|
||||
for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) {
|
||||
printf(" %-10s %s\n", cmds[i].name, cmds[i].comment);
|
||||
@@ -62,11 +66,13 @@ void Usage(const char *message) {
|
||||
/* GUID conversion functions. Accepted format:
|
||||
*
|
||||
* "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
|
||||
*
|
||||
* Returns CGPT_OK if parsing is successful; otherwise CGPT_FAILED.
|
||||
*/
|
||||
void StrToGuid(const char *str, Guid *guid) {
|
||||
int StrToGuid(const char *str, Guid *guid) {
|
||||
uint32_t time_low, time_mid, time_high_and_version;
|
||||
|
||||
sscanf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
if (11 > sscanf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
&time_low,
|
||||
(unsigned int *)&time_mid,
|
||||
(unsigned int *)&time_high_and_version,
|
||||
@@ -77,11 +83,13 @@ void StrToGuid(const char *str, Guid *guid) {
|
||||
(unsigned int *)&guid->u.Uuid.node[2],
|
||||
(unsigned int *)&guid->u.Uuid.node[3],
|
||||
(unsigned int *)&guid->u.Uuid.node[4],
|
||||
(unsigned int *)&guid->u.Uuid.node[5]);
|
||||
(unsigned int *)&guid->u.Uuid.node[5])) return CGPT_FAILED;
|
||||
|
||||
guid->u.Uuid.time_low = htole32(time_low);
|
||||
guid->u.Uuid.time_mid = htole16(time_mid);
|
||||
guid->u.Uuid.time_high_and_version = htole16(time_high_and_version);
|
||||
|
||||
return CGPT_OK;
|
||||
}
|
||||
|
||||
void GuidToStr(const Guid *guid, char *str) {
|
||||
@@ -194,6 +202,54 @@ void UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16)
|
||||
utf16[s16idx++] = 0;
|
||||
}
|
||||
|
||||
struct {
|
||||
Guid type;
|
||||
char *name;
|
||||
char *description;
|
||||
} supported_types[] = {
|
||||
{GPT_ENT_TYPE_UNUSED, "unused", "Unused partition"},
|
||||
{GPT_ENT_TYPE_EFI, "efi", "EFI partition"},
|
||||
{GPT_ENT_TYPE_CHROMEOS_KERNEL, "croskern", "ChromeOS kernel"},
|
||||
{GPT_ENT_TYPE_CHROMEOS_ROOTFS, "crosroot", "ChromeOS rootfs"},
|
||||
{GPT_ENT_TYPE_CHROMEOS_RESERVED, "crosresv", "ChromeOS reserved"},
|
||||
};
|
||||
|
||||
/* Resolves human-readable GPT type.
|
||||
* Returns CGPT_OK if found.
|
||||
* Returns CGPT_FAILED if no known type found. */
|
||||
int ResolveType(const Guid *type, char *buf) {
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
|
||||
if (!Memcmp(type, &supported_types[i].type, sizeof(Guid))) {
|
||||
strcpy(buf, supported_types[i].description);
|
||||
return CGPT_OK;
|
||||
}
|
||||
}
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
|
||||
int SupportedType(const char *name, Guid *type) {
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
|
||||
if (!strcmp(name, supported_types[i].name)) {
|
||||
Memcpy(type, &supported_types[i].type, sizeof(Guid));
|
||||
return CGPT_OK;
|
||||
}
|
||||
}
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
|
||||
void PrintTypes(void) {
|
||||
int i;
|
||||
printf("\n* For --type option, you can use the following alias, "
|
||||
"instead of hex values:\n");
|
||||
for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
|
||||
printf(" %-10s %s\n", supported_types[i].name,
|
||||
supported_types[i].description);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Loads sectors from 'fd'.
|
||||
* *buf is pointed to an allocated memory when returned, and should be
|
||||
* freed by cgpt_close().
|
||||
@@ -267,7 +323,7 @@ int CheckValid(const struct drive *drive) {
|
||||
if ((drive->gpt.valid_headers != MASK_BOTH) ||
|
||||
(drive->gpt.valid_entries != MASK_BOTH)) {
|
||||
printf("\n[ERROR] any of GPT header/entries is invalid, "
|
||||
"please run --repair first\n");
|
||||
"please run '%s repair' first\n", progname);
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
return CGPT_OK;
|
||||
@@ -316,9 +372,6 @@ int DriveOpen(const char *drive_path, struct drive *drive) {
|
||||
goto error_close;
|
||||
}
|
||||
drive->gpt.drive_sectors = drive->size / drive->gpt.sector_bytes;
|
||||
debug("drive: size:%llu sector_size:%d num_sector:%llu\n",
|
||||
(long long unsigned int)drive->size, drive->gpt.sector_bytes,
|
||||
(long long unsigned int)drive->gpt.drive_sectors);
|
||||
|
||||
Load(drive->fd, &drive->gpt.primary_header, GPT_PMBR_SECTOR,
|
||||
drive->gpt.sector_bytes, GPT_HEADER_SECTOR);
|
||||
@@ -390,6 +443,7 @@ int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
|
||||
progname = argv[0];
|
||||
printf("Copyright (c) 2010 The Chromium OS Authors. All rights reserved.\n");
|
||||
cmd = argv[optind++];
|
||||
for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) {
|
||||
if (cmd && !strcmp(cmds[i].name, cmd))
|
||||
|
||||
@@ -51,13 +51,15 @@ struct option_details {
|
||||
* i.e. help, to indicate the option is present. */
|
||||
int AssignTrue(const char *argument, void *pointer, void *integer);
|
||||
|
||||
/* Special validator. Copy string to 'parsed' with max 'valid_range' bytes. */
|
||||
int CopyString(const char *argument, void *max_len, void *dst);
|
||||
|
||||
/* Validator function. Returns 1 if 'argument' is between 'max' and 'min'
|
||||
* in 'valid_range'. */
|
||||
struct number_range {
|
||||
int max;
|
||||
int min;
|
||||
};
|
||||
|
||||
/* Validator function. Returns 1 if 'argument' is between 'max' and 'min'
|
||||
* in 'valid_range'. */
|
||||
int InNumberRange(const char *argument, void *valid_range, void *parsed);
|
||||
|
||||
void ShowOptions(const struct option *opts,
|
||||
@@ -97,7 +99,7 @@ int OpenDriveInLastArgument(const int argc,
|
||||
* '\0').
|
||||
*/
|
||||
#define GUID_STRLEN 37
|
||||
void StrToGuid(const char *str, Guid *guid);
|
||||
int StrToGuid(const char *str, Guid *guid);
|
||||
void GuidToStr(const Guid *guid, char *str);
|
||||
|
||||
/* Convert UTF16 string to UTF8. Rewritten from gpt utility.
|
||||
@@ -113,6 +115,11 @@ void UTF16ToUTF8(const uint16_t *utf16, uint8_t *utf8);
|
||||
*/
|
||||
void UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16);
|
||||
|
||||
/* Helper functions for supported GPT types. */
|
||||
int ResolveType(const Guid *type, char *buf);
|
||||
int SupportedType(const char *name, Guid *type);
|
||||
void PrintTypes(void);
|
||||
|
||||
/* Describes the drive storing the GPT. */
|
||||
struct drive {
|
||||
int inited; /* indicated if this structure is valid */
|
||||
@@ -140,7 +147,9 @@ int CheckValid(const struct drive *drive);
|
||||
|
||||
/* Function declarations for commands.
|
||||
* The return value of these functions is passed to main()'s exit value. */
|
||||
int CgptAdm(int argc, char *argv[]);
|
||||
int CgptAttribute(int argc, char *argv[]);
|
||||
int CgptDev(int argc, char *argv[]);
|
||||
int CgptRepair(int argc, char *argv[]);
|
||||
int CgptShow(int argc, char *argv[]);
|
||||
|
||||
|
||||
276
utility/cgpt/cgpt_add_modify_delete.c
Normal file
276
utility/cgpt/cgpt_add_modify_delete.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/* Copyright (c) 2010 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.
|
||||
*
|
||||
* Update GPT attribute bits.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cgpt.h"
|
||||
#include "cgptlib_internal.h"
|
||||
#include "utility.h"
|
||||
|
||||
static struct number_range
|
||||
range_127_0 = {127, 0};
|
||||
|
||||
/* Integers to store parsed argument. */
|
||||
static int help, partition, begin_lba, size_lba;
|
||||
static char type[128], unique[128], name[128];
|
||||
|
||||
/* The structure for getopt_long(). When you add/delete any line, please refine
|
||||
* attribute_comments[] and third parameter of getopt_long() too. */
|
||||
static struct option adm_options[] = {
|
||||
{.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'},
|
||||
{.name = "partition", .has_arg = required_argument, .flag = 0, .val = 'i'},
|
||||
#if 0//FIXME
|
||||
{.name = "bad", .has_arg = required_argument, .flag = 0, .val = 'b'},
|
||||
{.name = "successful", .has_arg = required_argument, .flag = 0, .val = 's'},
|
||||
{.name = "tries", .has_arg = required_argument, .flag = 0, .val = 't'},
|
||||
{.name = "priority", .has_arg = required_argument, .flag = 0, .val = 'p'},
|
||||
#endif
|
||||
{.name = "type", .has_arg = required_argument, .flag = 0, .val = 't'},
|
||||
{.name = "unique", .has_arg = required_argument, .flag = 0, .val = 'u'},
|
||||
{.name = "begin", .has_arg = required_argument, .flag = 0, .val = 'b'},
|
||||
{.name = "size", .has_arg = required_argument, .flag = 0, .val = 's'},
|
||||
{.name = "name", .has_arg = required_argument, .flag = 0, .val = 'n'},
|
||||
{ /* last element, which should be zero. */ }
|
||||
};
|
||||
|
||||
/* Extra information than struct option, please update this structure if you
|
||||
* add/remove any line in attribute_options[]. */
|
||||
static struct option_details adm_options_details[] = {
|
||||
/* help */
|
||||
{ .comment = "print this help",
|
||||
.validator = AssignTrue,
|
||||
.valid_range = 0,
|
||||
.parsed = &help},
|
||||
/* partition */
|
||||
{ .comment = "partition number (MUST HAVE)",
|
||||
.validator = InNumberRange,
|
||||
.valid_range = &range_127_0,
|
||||
.parsed = &partition},
|
||||
#if 0//FIXME
|
||||
/* bad */
|
||||
{ .comment = "mark partition bad",
|
||||
.validator = InNumberRange,
|
||||
.valid_range = &range_1_0,
|
||||
.parsed = &bad},
|
||||
/* successful */
|
||||
{ .comment = "mark partition successful",
|
||||
.validator = InNumberRange,
|
||||
.valid_range = &range_1_0,
|
||||
.parsed = &successful},
|
||||
/* tries */
|
||||
{ .comment = "tries",
|
||||
.validator = InNumberRange,
|
||||
.valid_range = &range_15_0,
|
||||
.parsed = &tries},
|
||||
/* priority */
|
||||
{ .comment = "priority to boot",
|
||||
.validator = InNumberRange,
|
||||
.valid_range = &range_15_0,
|
||||
.parsed = &priority},
|
||||
#endif
|
||||
/* type */
|
||||
{ .comment = "Partition Type (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)",
|
||||
.validator = CopyString,
|
||||
.valid_range = (void*)sizeof(type),
|
||||
.parsed = &type},
|
||||
/* uuid */
|
||||
{ .comment = "Partition UUID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)",
|
||||
.validator = CopyString,
|
||||
.valid_range = (void*)sizeof(unique),
|
||||
.parsed = &unique},
|
||||
/* start */
|
||||
{ .comment = "starting LBA",
|
||||
.validator = InNumberRange,
|
||||
.valid_range = 0,
|
||||
.parsed = &begin_lba},
|
||||
/* end */
|
||||
{ .comment = "ending LBA",
|
||||
.validator = InNumberRange,
|
||||
.valid_range = 0,
|
||||
.parsed = &size_lba},
|
||||
/* name */
|
||||
{ .comment = "Partition name",
|
||||
.validator = CopyString,
|
||||
.valid_range = (void*)sizeof(name),
|
||||
.parsed = &name},
|
||||
{ /* last element, which should be zero. */ }
|
||||
};
|
||||
|
||||
void AdmHelp() {
|
||||
printf("\nUsage: %s {add|delete|modify} [OPTIONS] device_name\n\n", progname);
|
||||
ShowOptions(adm_options, adm_options_details, ARRAY_COUNT(adm_options));
|
||||
PrintTypes();
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
enum {
|
||||
ADD,
|
||||
DELETE,
|
||||
MODIFY,
|
||||
} command;
|
||||
|
||||
/* Parses all options (and validates them), then opens the drive and sets
|
||||
* corresponding bits in GPT entry. */
|
||||
int CgptAdm(int argc, char *argv[]) {
|
||||
struct drive drive;
|
||||
char *cmd;
|
||||
GptEntry *entry;
|
||||
Guid type_guid, unique_guid;
|
||||
int dirty = 0;
|
||||
|
||||
/* I know this is NOT the perfect place to put code to make options[] and
|
||||
* details[] are synced. But this is the best place we have right now since C
|
||||
* preprocessor doesn't know sizeof() for #if directive. */
|
||||
assert(ARRAY_COUNT(adm_options) ==
|
||||
ARRAY_COUNT(adm_options_details));
|
||||
|
||||
cmd = argv[optind - 1];
|
||||
if (!strcmp("add", cmd)) command = ADD;
|
||||
else if (!strcmp("delete", cmd)) command = DELETE;
|
||||
else if (!strcmp("modify", cmd)) command = MODIFY;
|
||||
|
||||
#if 0//FIXME
|
||||
help = partition = bad = successful = tries = priority =
|
||||
#endif
|
||||
help = partition = begin_lba = size_lba = NOT_INITED;
|
||||
type[0] = '\0';
|
||||
unique[0] = '\0';
|
||||
name[0] = '\0';
|
||||
|
||||
if (CGPT_OK != HandleOptions(argc, argv,
|
||||
"hi:t:u:b:s:n:",
|
||||
ARRAY_COUNT(adm_options),
|
||||
adm_options,
|
||||
adm_options_details))
|
||||
return CGPT_FAILED;
|
||||
if (help != NOT_INITED) {
|
||||
AdmHelp();
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
|
||||
if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive))
|
||||
return CGPT_FAILED;
|
||||
|
||||
if (CheckValid(&drive) != CGPT_OK) goto error_close;
|
||||
|
||||
if (partition == NOT_INITED) {
|
||||
printf("[ERROR] Please provide partition number with --partition or -i.\n");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
entry = GetEntry(&drive.gpt, PRIMARY, partition);
|
||||
/* check before really doing something. */
|
||||
switch (command) {
|
||||
case ADD:
|
||||
if (NonZeroGuid(&entry->type)) {
|
||||
printf("[ERROR] partition %d is not free, use '%s modify' instead.\n",
|
||||
partition, progname);
|
||||
goto error_close;
|
||||
}
|
||||
if (type[0] == '\0') {
|
||||
printf("* You must give a type with '--type' or '-t'.\n");
|
||||
PrintTypes();
|
||||
goto error_close;
|
||||
}
|
||||
if (begin_lba == NOT_INITED) {
|
||||
printf("* You didn't give the begin LBA, use '--begin' to specify.\n");
|
||||
goto error_close;
|
||||
}
|
||||
if (size_lba == NOT_INITED) {
|
||||
printf("* You didn't give size, use '--size' to specify.\n");
|
||||
goto error_close;
|
||||
}
|
||||
break;
|
||||
case DELETE:
|
||||
if (!NonZeroGuid(&entry->type)) {
|
||||
printf("[ERROR] partition %d is free already.\n", partition);
|
||||
goto error_close;
|
||||
}
|
||||
break;
|
||||
case MODIFY:
|
||||
if (!NonZeroGuid(&entry->type)) {
|
||||
printf("[ERROR] partition %d is free, use '%s add' first.\n",
|
||||
partition, progname);
|
||||
goto error_close;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0 //FIXME
|
||||
if (bad != NOT_INITED)
|
||||
SetBad(&drive.gpt, PRIMARY, partition, bad);
|
||||
if (successful != NOT_INITED)
|
||||
SetSuccessful(&drive.gpt, PRIMARY, partition, successful);
|
||||
if (tries != NOT_INITED)
|
||||
SetTries(&drive.gpt, PRIMARY, partition, tries);
|
||||
if (priority != NOT_INITED)
|
||||
SetPriority(&drive.gpt, PRIMARY, partition, priority);
|
||||
#endif
|
||||
if (type[0]) {
|
||||
if (CGPT_OK != SupportedType(type, &type_guid) &&
|
||||
CGPT_OK != StrToGuid(type, &type_guid)) {
|
||||
printf("[ERROR] You didn't give a valid type [%s]\n", type);
|
||||
goto error_close;
|
||||
}
|
||||
Memcpy(&entry->type, &type_guid, sizeof(Guid));
|
||||
++dirty;
|
||||
}
|
||||
if (unique[0]) {
|
||||
if (CGPT_OK != StrToGuid(unique, &unique_guid)) {
|
||||
printf("[ERROR] You didn't give a valid UUID [%s]\n", unique);
|
||||
goto error_close;
|
||||
}
|
||||
Memcpy(&entry->unique, &unique_guid, sizeof(Guid));
|
||||
++dirty;
|
||||
}
|
||||
if (begin_lba != NOT_INITED) {
|
||||
entry->starting_lba = begin_lba;
|
||||
++dirty;
|
||||
}
|
||||
if (size_lba != NOT_INITED) {
|
||||
entry->ending_lba = entry->starting_lba + size_lba - 1;
|
||||
++dirty;
|
||||
}
|
||||
if (name[0]) {
|
||||
UTF8ToUTF16((uint8_t*)name, entry->name);
|
||||
++dirty;
|
||||
}
|
||||
|
||||
if (command == DELETE) {
|
||||
Guid unused = GPT_ENT_TYPE_UNUSED;
|
||||
Memcpy(&entry->type, &unused, sizeof(Guid));
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
uint32_t valid_entries;
|
||||
|
||||
valid_entries = drive.gpt.valid_entries;
|
||||
if ((valid_entries != CheckValidEntries(&drive.gpt)) ||
|
||||
(valid_entries != CheckOverlappedPartition(&drive.gpt))) {
|
||||
printf("\n[ERROR] Your change makes GPT invalid (or worse). "
|
||||
"Please check your arguments.\n\n");
|
||||
drive.gpt.modified = 0; /* DriveClose() won't update hard drive. */
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
/* Claims primary is good, then secondary will be overwritten. */
|
||||
RepairEntries(&drive.gpt, MASK_PRIMARY);
|
||||
RepairHeader(&drive.gpt, MASK_PRIMARY);
|
||||
|
||||
/* Forces headers and entries are modified so that CRC32 will be
|
||||
* re-calculated and headers and entries will be updated to drive. */
|
||||
drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
|
||||
GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
|
||||
UpdateCrc(&drive.gpt);
|
||||
}
|
||||
DriveClose(&drive);
|
||||
return CGPT_OK;
|
||||
|
||||
error_close:
|
||||
DriveClose(&drive);
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
@@ -27,6 +27,7 @@ static struct option attribute_options[] = {
|
||||
{.name = "successful", .has_arg = required_argument, .flag = 0, .val = 's'},
|
||||
{.name = "tries", .has_arg = required_argument, .flag = 0, .val = 't'},
|
||||
{.name = "priority", .has_arg = required_argument, .flag = 0, .val = 'p'},
|
||||
{ /* last element, which should be zero. */ }
|
||||
};
|
||||
|
||||
/* Extra information than struct option, please update this structure if you
|
||||
@@ -63,6 +64,7 @@ static struct option_details attribute_options_details[] = {
|
||||
.validator = InNumberRange,
|
||||
.valid_range = &range_15_0,
|
||||
.parsed = &priority},
|
||||
{ /* last element, which should be zero. */ }
|
||||
};
|
||||
|
||||
void AttributeHelp() {
|
||||
@@ -101,8 +103,6 @@ int CgptAttribute(int argc, char *argv[]) {
|
||||
|
||||
if (CheckValid(&drive) != CGPT_OK) return CGPT_FAILED;
|
||||
|
||||
debug("[OPTION] i:%d b:%d s:%d t:%d p:%d\n", partition, bad, successful, tries, priority); /* FIXME */
|
||||
|
||||
/* partition is not specified, search for the first Chromeos kernel. */
|
||||
if (partition == NOT_INITED) {
|
||||
int i;
|
||||
|
||||
126
utility/cgpt/cgpt_dev.c
Normal file
126
utility/cgpt/cgpt_dev.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/* Copyright (c) 2010 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.
|
||||
*
|
||||
* Developper mode.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cgpt.h"
|
||||
#include "cgptlib_internal.h"
|
||||
#include "utility.h"
|
||||
|
||||
/* Integers to store parsed argument. */
|
||||
static int help, primary_header, primary_entries,
|
||||
secondary_header, secondary_entries;
|
||||
|
||||
/* The structure for getopt_long(). When you add/delete any line, please refine
|
||||
* attribute_comments[] and third parameter of getopt_long() too. */
|
||||
static struct option dev_options[] = {
|
||||
{.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'},
|
||||
{.name = "primary-header", .has_arg = no_argument, .flag = 0, .val = 'a'},
|
||||
{.name = "primary-entries", .has_arg = no_argument, .flag = 0, .val = 'b'},
|
||||
{.name = "secondary-entries", .has_arg = no_argument, .flag = 0, .val = 'c'},
|
||||
{.name = "secondary-header", .has_arg = no_argument, .flag = 0, .val = 'd'},
|
||||
{ /* last element, which should be zero. */ }
|
||||
};
|
||||
|
||||
/* Extra information than struct option, please update this structure if you
|
||||
* add/remove any line in attribute_options[]. */
|
||||
static struct option_details dev_options_details[] = {
|
||||
/* help */
|
||||
{ .comment = "print this help",
|
||||
.validator = AssignTrue,
|
||||
.valid_range = 0,
|
||||
.parsed = &help},
|
||||
/* primary-header */
|
||||
{ .comment = "damage primary header",
|
||||
.validator = AssignTrue,
|
||||
.valid_range = 0,
|
||||
.parsed = &primary_header},
|
||||
/* primary-entries */
|
||||
{ .comment = "damage primary entries",
|
||||
.validator = AssignTrue,
|
||||
.valid_range = 0,
|
||||
.parsed = &primary_entries},
|
||||
/* secondary-entries */
|
||||
{ .comment = "damage secondary entries",
|
||||
.validator = AssignTrue,
|
||||
.valid_range = 0,
|
||||
.parsed = &secondary_entries},
|
||||
/* secondary-header */
|
||||
{ .comment = "damage secondary header",
|
||||
.validator = AssignTrue,
|
||||
.valid_range = 0,
|
||||
.parsed = &secondary_header},
|
||||
{ /* last element, which should be zero. */ }
|
||||
};
|
||||
|
||||
void DevHelp() {
|
||||
printf("\nDeveloper mode.\n\n");
|
||||
printf("\nUsage: %s dev [OPTIONS] device_name\n\n", progname);
|
||||
ShowOptions(dev_options, dev_options_details, ARRAY_COUNT(dev_options));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Very simple function, you may choose damage one or more of the following
|
||||
* sections:
|
||||
*
|
||||
* Primary GPT header
|
||||
* Primary GPT table entries
|
||||
* Secondary GPT table entries
|
||||
* Secondary GPT header
|
||||
*/
|
||||
int CgptDev(int argc, char *argv[]) {
|
||||
struct drive drive;
|
||||
|
||||
/* I know this is NOT the perfect place to put code to make options[] and
|
||||
* details[] are synced. But this is the best place we have right now since C
|
||||
* preprocessor doesn't know sizeof() for #if directive. */
|
||||
assert(ARRAY_COUNT(dev_options) ==
|
||||
ARRAY_COUNT(dev_options_details));
|
||||
|
||||
help = primary_header = primary_entries =
|
||||
secondary_header = secondary_entries = NOT_INITED;
|
||||
|
||||
if (CGPT_OK != HandleOptions(argc, argv,
|
||||
"h",
|
||||
ARRAY_COUNT(dev_options),
|
||||
dev_options,
|
||||
dev_options_details))
|
||||
return CGPT_FAILED;
|
||||
if (help != NOT_INITED) {
|
||||
DevHelp();
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
|
||||
if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive))
|
||||
return CGPT_FAILED;
|
||||
|
||||
#define ANY_PRIME 7
|
||||
if (primary_header != NOT_INITED) {
|
||||
printf("* damage Pri Header\n");
|
||||
drive.gpt.primary_header[0] += ANY_PRIME;
|
||||
drive.gpt.modified |= GPT_MODIFIED_HEADER1;
|
||||
}
|
||||
if (primary_entries != NOT_INITED) {
|
||||
printf("* damage Pri Table\n");
|
||||
drive.gpt.primary_entries[0] += ANY_PRIME;
|
||||
drive.gpt.modified |= GPT_MODIFIED_ENTRIES1;
|
||||
}
|
||||
if (secondary_entries != NOT_INITED) {
|
||||
printf("* damage Sec Table\n");
|
||||
drive.gpt.secondary_entries[0] += ANY_PRIME;
|
||||
drive.gpt.modified |= GPT_MODIFIED_ENTRIES2;
|
||||
}
|
||||
if (secondary_header != NOT_INITED) {
|
||||
printf("* damage Sec Header\n");
|
||||
drive.gpt.secondary_header[0] += ANY_PRIME;
|
||||
drive.gpt.modified |= GPT_MODIFIED_HEADER2;
|
||||
}
|
||||
|
||||
DriveClose(&drive);
|
||||
|
||||
return CGPT_OK;
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
* Update GPT attribute bits.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cgpt.h"
|
||||
@@ -16,6 +17,12 @@ int AssignTrue(const char *argument, void *pointer, void *integer) {
|
||||
return CGPT_OK;
|
||||
}
|
||||
|
||||
/* Special validator. Copy string to 'parsed' with max 'valid_range' bytes. */
|
||||
int CopyString(const char *argument, void *max_len, void *dst) {
|
||||
Memcpy(dst, argument, (intptr_t)max_len);
|
||||
return CGPT_OK;
|
||||
}
|
||||
|
||||
/* Validator function. Returns 1 if 'argument' is between 'max' and 'min'
|
||||
* in 'valid_range'. */
|
||||
int InNumberRange(const char *argument, void *valid_range, void *parsed) {
|
||||
@@ -23,14 +30,13 @@ int InNumberRange(const char *argument, void *valid_range, void *parsed) {
|
||||
char *endptr;
|
||||
int number;
|
||||
|
||||
assert(valid_range);
|
||||
|
||||
number = strtol(argument, &endptr, 10);
|
||||
if (*endptr) {
|
||||
printf("[ERROR] argument '%s' is not a number.\n", argument);
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
|
||||
if (range) {
|
||||
if (number < range->min) {
|
||||
printf("[ERROR] argument is too small (min is %d, but you gave: %d).\n",
|
||||
range->min, number);
|
||||
@@ -43,6 +49,11 @@ int InNumberRange(const char *argument, void *valid_range, void *parsed) {
|
||||
if (parsed) *(int*)parsed = number;
|
||||
return CGPT_OK;
|
||||
}
|
||||
} else {
|
||||
/* no range to check, assign integer. */
|
||||
if (parsed) *(int*)parsed = number;
|
||||
return CGPT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void ShowOptions(const struct option *opts,
|
||||
@@ -51,6 +62,7 @@ void ShowOptions(const struct option *opts,
|
||||
int i;
|
||||
for (i = 0; i < num; ++i) {
|
||||
char buf[32];
|
||||
if (!opts[i].name) break;
|
||||
snprintf(buf, sizeof(buf), "--%s %s", opts[i].name,
|
||||
opts[i].has_arg ? "ARG" : "");
|
||||
printf(" %-20s (-%c) %s\n", buf, opts[i].val, details[i].comment);
|
||||
@@ -76,6 +88,14 @@ int HandleOptions(const int argc,
|
||||
break;
|
||||
} else if (option == 0) {
|
||||
/* option 'val' has been saved in 'flag'. We do nothing here. */
|
||||
} else if (option == ':') {
|
||||
printf("[ERROR] Missing parameter for option.\n");
|
||||
ShowOptions(options, details, option_count);
|
||||
return CGPT_FAILED;
|
||||
} else if (option == '?') {
|
||||
printf("[ERROR] unknown option name: %s\n", argv[optind - 1]);
|
||||
ShowOptions(options, details, option_count);
|
||||
return CGPT_FAILED;
|
||||
} else {
|
||||
/* Short option doesn't update 'index'. We search whole array to find out
|
||||
* the corresponding long option. */
|
||||
|
||||
@@ -20,6 +20,7 @@ static int help;
|
||||
* attribute_comments[] and third parameter of getopt_long() too. */
|
||||
static struct option repair_options[] = {
|
||||
{.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'},
|
||||
{ /* last element, which should be zero. */ }
|
||||
};
|
||||
|
||||
/* Extra information than struct option, please update this structure if you
|
||||
@@ -30,6 +31,7 @@ static struct option_details repair_options_details[] = {
|
||||
.validator = AssignTrue,
|
||||
.valid_range = 0,
|
||||
.parsed = &help},
|
||||
{ /* last element, which should be zero. */ }
|
||||
};
|
||||
|
||||
void RepairHelp() {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*
|
||||
* Update GPT attribute bits.
|
||||
* Show GPT details.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
@@ -20,6 +20,7 @@ static struct option show_options[] = {
|
||||
{.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'},
|
||||
{.name = "number", .has_arg = no_argument, .flag = 0, .val = 'n'},
|
||||
{.name = "verbose", .has_arg = no_argument, .flag = 0, .val = 'v'},
|
||||
{ /* last element, which should be zero. */ }
|
||||
};
|
||||
|
||||
/* Extra information than struct option, please update this structure if you
|
||||
@@ -40,6 +41,7 @@ static struct option_details show_options_details[] = {
|
||||
.validator = AssignTrue,
|
||||
.valid_range = 0,
|
||||
.parsed = &verbose},
|
||||
{ /* last element, which should be zero. */ }
|
||||
};
|
||||
|
||||
void ShowHelp() {
|
||||
@@ -121,31 +123,6 @@ static void HeaderDetails(GptHeader *header, const char *indent) {
|
||||
printf("%sEntries CRC: 0x%08x\n", indent, header->entries_crc32);
|
||||
}
|
||||
|
||||
/* Resolves human-readable GPT type.
|
||||
* Returns CGPT_OK if found.
|
||||
* Returns CGPT_FAILED if no known type found. */
|
||||
int ResolveType(const Guid *type, char *buf) {
|
||||
struct {
|
||||
Guid type;
|
||||
char *description;
|
||||
} known[] = {
|
||||
{GPT_ENT_TYPE_UNUSED, "Unused partition"},
|
||||
{GPT_ENT_TYPE_EFI, "EFI partition"},
|
||||
{GPT_ENT_TYPE_CHROMEOS_KERNEL, "ChromeOS kernel"},
|
||||
{GPT_ENT_TYPE_CHROMEOS_ROOTFS, "ChromeOS rootfs"},
|
||||
{GPT_ENT_TYPE_CHROMEOS_RESERVED, "ChromeOS reserved"},
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(known); ++i) {
|
||||
if (!Memcmp(type, &known[i].type, sizeof(Guid))) {
|
||||
strcpy(buf, known[i].description);
|
||||
return CGPT_OK;
|
||||
}
|
||||
}
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
|
||||
void EntriesDetails(GptData *gpt, const int secondary) {
|
||||
int i;
|
||||
|
||||
@@ -236,6 +213,7 @@ int CgptShow(int argc, char *argv[]) {
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
|
||||
OpenDriveInLastArgument(argc, argv, &drive);
|
||||
if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive))
|
||||
return CGPT_FAILED;
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@ int CheckParameters(GptData *gpt) {
|
||||
|
||||
/* Expects header signature should be GPT_HEADER_SIGNATURE. */
|
||||
uint32_t CheckHeaderSignature(GptData *gpt) {
|
||||
uint32_t valid_headers = MASK_BOTH;
|
||||
GptHeader *headers[] = {
|
||||
(GptHeader*)gpt->primary_header,
|
||||
(GptHeader*)gpt->secondary_header,
|
||||
@@ -69,15 +68,14 @@ uint32_t CheckHeaderSignature(GptData *gpt) {
|
||||
if (Memcmp(headers[i]->signature,
|
||||
GPT_HEADER_SIGNATURE,
|
||||
GPT_HEADER_SIGNATURE_SIZE)) {
|
||||
INVALIDATE_HEADER(valid_headers, i);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, i);
|
||||
}
|
||||
}
|
||||
return valid_headers;
|
||||
return gpt->valid_headers;
|
||||
}
|
||||
|
||||
/* The header revision should be GPT_HEADER_REVISION. */
|
||||
uint32_t CheckRevision(GptData *gpt) {
|
||||
uint32_t valid_headers = MASK_BOTH;
|
||||
GptHeader *headers[] = {
|
||||
(GptHeader*)gpt->primary_header,
|
||||
(GptHeader*)gpt->secondary_header,
|
||||
@@ -86,15 +84,14 @@ uint32_t CheckRevision(GptData *gpt) {
|
||||
|
||||
for (i = PRIMARY; i <= SECONDARY; ++i) {
|
||||
if (headers[i]->revision != GPT_HEADER_REVISION)
|
||||
INVALIDATE_HEADER(valid_headers, i);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, i);
|
||||
}
|
||||
return valid_headers;
|
||||
return gpt->valid_headers;
|
||||
}
|
||||
|
||||
/* A valid header size should be between MIN_SIZE_OF_HEADER and
|
||||
* MAX_SIZE_OF_HEADER. */
|
||||
uint32_t CheckSize(GptData *gpt) {
|
||||
uint32_t valid_headers = MASK_BOTH;
|
||||
GptHeader *headers[] = {
|
||||
(GptHeader*)gpt->primary_header,
|
||||
(GptHeader*)gpt->secondary_header,
|
||||
@@ -104,14 +101,13 @@ uint32_t CheckSize(GptData *gpt) {
|
||||
for (i = PRIMARY; i <= SECONDARY; ++i) {
|
||||
if ((headers[i]->size < MIN_SIZE_OF_HEADER) ||
|
||||
(headers[i]->size > MAX_SIZE_OF_HEADER))
|
||||
INVALIDATE_HEADER(valid_headers, i);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, i);
|
||||
}
|
||||
return valid_headers;
|
||||
return gpt->valid_headers;
|
||||
}
|
||||
|
||||
/* Reserved and padding fields should be zero. */
|
||||
uint32_t CheckReservedFields(GptData *gpt) {
|
||||
uint32_t valid_headers = MASK_BOTH;
|
||||
GptHeader *headers[] = {
|
||||
(GptHeader*)gpt->primary_header,
|
||||
(GptHeader*)gpt->secondary_header,
|
||||
@@ -120,32 +116,30 @@ uint32_t CheckReservedFields(GptData *gpt) {
|
||||
|
||||
for (i = PRIMARY; i <= SECONDARY; ++i) {
|
||||
if (headers[i]->reserved || headers[i]->padding)
|
||||
INVALIDATE_HEADER(valid_headers, i);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, i);
|
||||
}
|
||||
return valid_headers;
|
||||
return gpt->valid_headers;
|
||||
}
|
||||
|
||||
/* my_lba field points to the header itself.
|
||||
* So that the my_lba of primary header should be 1 (right after PMBR).
|
||||
* The my_lba of secondary header should be the last secotr on drive. */
|
||||
uint32_t CheckMyLba(GptData *gpt) {
|
||||
uint32_t valid_headers = MASK_BOTH;
|
||||
GptHeader *primary_header, *secondary_header;
|
||||
|
||||
primary_header = (GptHeader*)gpt->primary_header;
|
||||
secondary_header = (GptHeader*)gpt->secondary_header;
|
||||
|
||||
if (primary_header->my_lba != GPT_PMBR_SECTOR) /* 2nd sector on drive */
|
||||
INVALIDATE_HEADER(valid_headers, PRIMARY);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, PRIMARY);
|
||||
if (secondary_header->my_lba != (gpt->drive_sectors - 1)) /* last sector */
|
||||
INVALIDATE_HEADER(valid_headers, SECONDARY);
|
||||
return valid_headers;
|
||||
INVALIDATE_HEADER(gpt->valid_headers, SECONDARY);
|
||||
return gpt->valid_headers;
|
||||
}
|
||||
|
||||
/* SizeOfPartitionEntry must be between MIN_SIZE_OF_ENTRY and
|
||||
* MAX_SIZE_OF_ENTRY, and a multiple of SIZE_OF_ENTRY_MULTIPLE. */
|
||||
uint32_t CheckSizeOfPartitionEntry(GptData *gpt) {
|
||||
uint32_t valid_headers = MASK_BOTH;
|
||||
GptHeader *headers[] = {
|
||||
(GptHeader*)gpt->primary_header,
|
||||
(GptHeader*)gpt->secondary_header,
|
||||
@@ -157,16 +151,15 @@ uint32_t CheckSizeOfPartitionEntry(GptData *gpt) {
|
||||
if ((size_of_entry < MIN_SIZE_OF_ENTRY) ||
|
||||
(size_of_entry > MAX_SIZE_OF_ENTRY) ||
|
||||
(size_of_entry & (SIZE_OF_ENTRY_MULTIPLE - 1)))
|
||||
INVALIDATE_HEADER(valid_headers, i);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, i);
|
||||
}
|
||||
return valid_headers;
|
||||
return gpt->valid_headers;
|
||||
}
|
||||
|
||||
/* number_of_entries must be between MIN_NUMBER_OF_ENTRIES and
|
||||
* MAX_NUMBER_OF_ENTRIES, and size_of_entry * number_of_entries must be
|
||||
* equal to TOTAL_ENTRIES_SIZE. */
|
||||
uint32_t CheckNumberOfEntries(GptData *gpt) {
|
||||
uint32_t valid_headers = MASK_BOTH;
|
||||
GptHeader *headers[] = {
|
||||
(GptHeader*)gpt->primary_header,
|
||||
(GptHeader*)gpt->secondary_header,
|
||||
@@ -178,16 +171,15 @@ uint32_t CheckNumberOfEntries(GptData *gpt) {
|
||||
if ((number_of_entries < MIN_NUMBER_OF_ENTRIES) ||
|
||||
(number_of_entries > MAX_NUMBER_OF_ENTRIES) ||
|
||||
(number_of_entries * headers[i]->size_of_entry != TOTAL_ENTRIES_SIZE))
|
||||
INVALIDATE_HEADER(valid_headers, i);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, i);
|
||||
}
|
||||
return valid_headers;
|
||||
return gpt->valid_headers;
|
||||
}
|
||||
|
||||
/* Make sure entries_lba is correct.
|
||||
* 2 for primary entries
|
||||
* drive_sectors-1-GPT_ENTRIES_SECTORS for secondary entries. */
|
||||
uint32_t CheckEntriesLba(GptData *gpt) {
|
||||
uint32_t valid_headers = MASK_BOTH;
|
||||
GptHeader *primary_header, *secondary_header;
|
||||
|
||||
primary_header = (GptHeader*)gpt->primary_header;
|
||||
@@ -196,20 +188,19 @@ uint32_t CheckEntriesLba(GptData *gpt) {
|
||||
/* We assume the primary partition entry table is located at the sector
|
||||
* right after primary partition header. */
|
||||
if (primary_header->entries_lba != (GPT_PMBR_SECTOR + GPT_HEADER_SECTOR))
|
||||
INVALIDATE_HEADER(valid_headers, PRIMARY);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, PRIMARY);
|
||||
/* We assume the secondary partition entry table is the 32 sectors
|
||||
* right before the secondary partition header. */
|
||||
if (secondary_header->entries_lba !=
|
||||
(gpt->drive_sectors - 1 - GPT_ENTRIES_SECTORS))
|
||||
INVALIDATE_HEADER(valid_headers, SECONDARY);
|
||||
return valid_headers;
|
||||
INVALIDATE_HEADER(gpt->valid_headers, SECONDARY);
|
||||
return gpt->valid_headers;
|
||||
}
|
||||
|
||||
/* FirstUsableLBA must be after the end of the primary GPT table array.
|
||||
* LastUsableLBA must be before the start of the secondary GPT table array.
|
||||
* FirstUsableLBA <= LastUsableLBA. */
|
||||
uint32_t CheckValidUsableLbas(GptData *gpt) {
|
||||
uint32_t valid_headers = MASK_BOTH;
|
||||
uint64_t end_of_primary_entries;
|
||||
uint64_t start_of_secondary_entries;
|
||||
GptHeader *headers[] = {
|
||||
@@ -224,20 +215,20 @@ uint32_t CheckValidUsableLbas(GptData *gpt) {
|
||||
|
||||
for (i = PRIMARY; i <= SECONDARY; ++i) {
|
||||
if (headers[i]->first_usable_lba < end_of_primary_entries)
|
||||
INVALIDATE_HEADER(valid_headers, i);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, i);
|
||||
if (headers[i]->last_usable_lba >= start_of_secondary_entries)
|
||||
INVALIDATE_HEADER(valid_headers, i);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, i);
|
||||
if (headers[i]->first_usable_lba > headers[i]->last_usable_lba)
|
||||
INVALIDATE_HEADER(valid_headers, i);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, i);
|
||||
}
|
||||
|
||||
if (headers[PRIMARY]->first_usable_lba - headers[PRIMARY]->entries_lba <
|
||||
GPT_ENTRIES_SECTORS)
|
||||
INVALIDATE_HEADER(valid_headers, PRIMARY);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, PRIMARY);
|
||||
if (headers[SECONDARY]->last_usable_lba >= headers[SECONDARY]->entries_lba)
|
||||
INVALIDATE_HEADER(valid_headers, SECONDARY);
|
||||
INVALIDATE_HEADER(gpt->valid_headers, SECONDARY);
|
||||
|
||||
return valid_headers;
|
||||
return gpt->valid_headers;
|
||||
}
|
||||
|
||||
/* Checks header CRC */
|
||||
@@ -289,7 +280,7 @@ uint32_t CheckEntriesCrc(GptData *gpt) {
|
||||
}
|
||||
|
||||
/* Returns non-zero if the given GUID is non-zero. */
|
||||
static int NonZeroGuid(const Guid *guid) {
|
||||
int NonZeroGuid(const Guid *guid) {
|
||||
static Guid zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
|
||||
return Memcmp(&zero, guid, sizeof(zero));
|
||||
}
|
||||
@@ -376,7 +367,6 @@ int OverlappedEntries(GptEntry *entries, uint32_t number_of_entries) {
|
||||
/* Checks if any two partitions are overlapped in primary and secondary entries.
|
||||
*/
|
||||
uint32_t CheckOverlappedPartition(GptData *gpt) {
|
||||
uint32_t valid_entries = MASK_BOTH;
|
||||
GptHeader *headers[] = {
|
||||
(GptHeader*)gpt->primary_header,
|
||||
(GptHeader*)gpt->secondary_header,
|
||||
@@ -395,9 +385,9 @@ uint32_t CheckOverlappedPartition(GptData *gpt) {
|
||||
|
||||
for (i = PRIMARY; i <= SECONDARY; ++i) {
|
||||
if (OverlappedEntries(entries[i], number_of_entries))
|
||||
INVALIDATE_ENTRIES(valid_entries, i);
|
||||
INVALIDATE_ENTRIES(gpt->valid_entries, i);
|
||||
}
|
||||
return valid_entries;
|
||||
return gpt->valid_entries;
|
||||
}
|
||||
|
||||
/* Primary entries and secondary entries should be bitwise identical.
|
||||
|
||||
@@ -21,6 +21,7 @@ uint32_t CheckEntriesLba(GptData *gpt);
|
||||
uint32_t CheckValidUsableLbas(GptData *gpt);
|
||||
uint32_t CheckHeaderCrc(GptData *gpt);
|
||||
uint32_t CheckEntriesCrc(GptData *gpt);
|
||||
int NonZeroGuid(const Guid *guid);
|
||||
uint32_t CheckValidEntries(GptData *gpt);
|
||||
typedef struct {
|
||||
uint64_t starting;
|
||||
|
||||
Reference in New Issue
Block a user