MTD search commands: show & find

BUG=chromium:221745
TEST=MTD version of run_cgpt_tests.sh passes
BRANCH=none

Change-Id: I8a5c1afab238eb10f38d865405ea2828715685d8
Original-Change-Id: I3d72fecbb3ef95252aa35d56885288340537b1c5
Reviewed-on: https://gerrit.chromium.org/gerrit/47175
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Commit-Queue: Albert Chaulk <achaulk@chromium.org>
Tested-by: Albert Chaulk <achaulk@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/49794
Reviewed-by: Albert Chaulk <achaulk@chromium.org>
This commit is contained in:
Albert Chaulk
2013-04-02 14:35:39 -07:00
committed by ChromeBot
parent 92f22e7c2a
commit 1c568bccc4
2 changed files with 286 additions and 62 deletions

View File

@@ -83,27 +83,37 @@ static void showmatch(CgptFindParams *params, char *filename,
EntryDetails(entry, partnum - 1, params->numeric);
}
// This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3, /dev/sda -> /dev/sda3
static void mtd_showmatch(CgptFindParams *params, char *filename,
int partnum, MtdDiskPartition *entry) {
char * format = "%s%d\n";
if (strncmp("/dev/mmcblk", filename, 11) == 0)
format = "%sp%d\n";
if (params->numeric)
printf("%d\n", partnum);
else
printf(format, filename, partnum);
if (params->verbose > 0)
MtdEntryDetails(entry, partnum - 1, params->numeric);
}
// This returns true if a GPT partition matches the search criteria. If a match
// isn't found (or if the file doesn't contain a GPT), it returns false. The
// filename and partition number that matched is left in a global, since we
// could have multiple hits.
static int do_search(CgptFindParams *params, char *fileName) {
int retval = 0;
static int gpt_search(CgptFindParams *params, struct drive *drive,
char *filename) {
int i;
struct drive drive;
GptEntry *entry;
int retval = 0;
char partlabel[GPT_PARTNAME_LEN];
if (CGPT_OK != DriveOpen(fileName, &drive, O_RDONLY))
return 0;
if (GPT_SUCCESS != GptSanityCheck(&drive.gpt)) {
(void) DriveClose(&drive, 0);
if (GPT_SUCCESS != GptSanityCheck(&drive->gpt)) {
return 0;
}
for (i = 0; i < GetNumberOfEntries(&drive); ++i) {
entry = GetEntry(&drive.gpt, ANY_VALID, i);
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
entry = GetEntry(&drive->gpt, ANY_VALID, i);
if (GuidIsZero(&entry->type))
continue;
@@ -122,15 +132,94 @@ static int do_search(CgptFindParams *params, char *fileName) {
if (!strncmp(params->label, partlabel, sizeof(partlabel)))
found = 1;
}
if (found && match_content(params, &drive, entry)) {
if (found && match_content(params, drive, entry)) {
params->hits++;
retval++;
showmatch(params, fileName, i+1, entry);
showmatch(params, filename, i+1, entry);
if (!params->match_partnum)
params->match_partnum = i+1;
}
}
return retval;
}
static int mtd_match_type_to_guid(const MtdDiskPartition *e, const Guid *guid) {
return LookupMtdTypeForGuid(guid) == MtdGetEntryType(e);
}
static int mtd_match_content(CgptFindParams *params, struct drive *drive,
MtdDiskPartition *entry) {
uint64_t part_size;
if (!params->matchlen)
return 1;
// Ensure that the region we want to match against is inside the partition.
part_size = LBA_SIZE * (entry->ending_lba - entry->starting_lba + 1);
if (params->matchoffset + params->matchlen > part_size) {
return 0;
}
// Read the partition data.
if (!FillBuffer(params,
drive->fd,
(LBA_SIZE * entry->starting_lba) + params->matchoffset,
params->matchlen)) {
Error("unable to read partition data\n");
return 0;
}
// Compare it
if (0 == memcmp(params->matchbuf, params->comparebuf, params->matchlen)) {
return 1;
}
// Nope.
return 0;
}
static int mtd_search(CgptFindParams *params, struct drive *drive,
char *filename) {
int i;
int retval = 0;
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
MtdDiskPartition *e = MtdGetEntry(&drive->mtd, ANY_VALID, i);
if (IsUnused(drive, ANY_VALID, i))
continue;
int found = 0;
// Only searches by type are possible right now
if (params->set_type && mtd_match_type_to_guid(e, &params->type_guid)) {
found = 1;
}
if (found && mtd_match_content(params, drive, e)) {
params->hits++;
retval++;
mtd_showmatch(params, filename, i+1, e);
if (!params->match_partnum)
params->match_partnum = i+1;
}
}
return retval;
}
static int do_search(CgptFindParams *params, char *fileName) {
int retval;
struct drive drive;
if (CGPT_OK != DriveOpen(fileName, &drive, O_RDONLY))
return 0;
if (drive.is_mtd) {
retval = mtd_search(params, &drive, fileName);
} else {
retval = gpt_search(params, &drive, fileName);
}
(void) DriveClose(&drive, 0);
return retval;

View File

@@ -49,22 +49,37 @@ static void RawDump(const uint8_t *memory, const int size,
#define PARTITION_FMT "%12d%12d%8d %s\n"
#define PARTITION_MORE "%12s%12s%8s %s%s\n", "", "", ""
static void HeaderDetails(GptHeader *header, GptEntry *entries,
const char *indent, int raw) {
int i;
void PrintSignature(const char *indent, const char *sig, size_t n, int raw) {
size_t i;
printf("%sSig: ", indent);
if (!raw) {
printf("[");
for (i = 0; i < sizeof(header->signature); ++i)
printf("%c", header->signature[i]);
for (i = 0; i < n; ++i)
printf("%c", sig[i]);
printf("]");
} else {
char buf[BUFFER_SIZE(sizeof(header->signature))];
RawDump((uint8_t *)header->signature, sizeof(header->signature), buf, 1);
char *buf = malloc(BUFFER_SIZE(n));
RawDump((uint8_t *)sig, n, buf, 1);
printf("%s", buf);
free(buf);
}
printf("\n");
}
void MtdHeaderDetails(MtdDiskLayout *header, const char *indent, int raw) {
PrintSignature(indent, (char*)header->signature, sizeof(header->signature),
raw);
printf("%sSize: %d\n", indent, header->size);
printf("%sCRC: 0x%08x %s\n", indent, header->crc32,
(MtdHeaderCrc(header) != header->crc32) ? "(INVALID)" : "");
printf("%sFirst LBA: %u\n", indent, header->first_lba);
printf("%sLast LBA: %u\n", indent, header->last_lba);
}
static void HeaderDetails(GptHeader *header, GptEntry *entries,
const char *indent, int raw) {
PrintSignature(indent, header->signature, sizeof(header->signature), raw);
printf("%sRev: 0x%08x\n", indent, header->revision);
printf("%sSize: %d\n", indent, header->size);
@@ -92,6 +107,26 @@ static void HeaderDetails(GptHeader *header, GptEntry *entries,
);
}
void MtdEntryDetails(MtdDiskPartition *entry, uint32_t index, int raw) {
const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
char buf[256]; // scratch buffer for formatting output
if (guid) {
ResolveType(guid, buf);
} else {
snprintf(buf, sizeof(buf), "MTD partition type %d", MtdGetEntryType(entry));
}
if (!raw) {
printf(PARTITION_FMT, (int)entry->starting_lba,
(int)(entry->ending_lba - entry->starting_lba + 1),
index+1, buf);
} else {
printf(PARTITION_FMT, (int)entry->starting_lba,
(int)(entry->ending_lba - entry->starting_lba + 1),
index+1, buf);
}
}
void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
char contents[256]; // scratch buffer for formatting output
uint8_t label[GPT_PARTNAME_LEN];
@@ -149,6 +184,17 @@ void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
}
}
void MtdEntriesDetails(struct drive *drive, int secondary, int raw) {
uint32_t i;
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
MtdDiskPartition *entry;
entry = MtdGetEntry(&drive->mtd, secondary, i);
if (IsUnused(drive, secondary, i))
continue;
MtdEntryDetails(entry, i, raw);
}
}
void EntriesDetails(struct drive *drive, const int secondary, int raw) {
uint32_t i;
@@ -200,17 +246,86 @@ done:
return retval;
}
int CgptShow(CgptShowParams *params) {
struct drive drive;
int MtdShow(struct drive *drive, CgptShowParams *params) {
if (params->partition) { // show single partition
if (params->partition > GetNumberOfEntries(drive)) {
Error("invalid partition number: %d\n", params->partition);
return CGPT_FAILED;
}
uint32_t index = params->partition - 1;
MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, index);
char buf[256]; // scratch buffer for string conversion
const Guid *guid;
if (params->single_item) {
switch(params->single_item) {
case 'b':
printf("%u\n", entry->starting_lba);
break;
case 's':
printf("%u\n", entry->ending_lba - entry->starting_lba + 1);
break;
case 't':
guid = LookupGuidForMtdType(MtdGetEntryType(entry));
GuidToStr(guid, buf, sizeof(buf));
printf("%s\n", buf);
break;
case 'S':
printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
break;
case 'T':
printf("%d\n", GetTries(drive, ANY_VALID, index));
break;
case 'P':
printf("%d\n", GetPriority(drive, ANY_VALID, index));
break;
case 'A':
printf("0x%x\n", entry->flags);
break;
}
} else {
printf(TITLE_FMT, "start", "size", "part", "contents");
MtdEntryDetails(entry, index, params->numeric);
}
} else if (params->quick) { // show all partitions, quickly
uint32_t i;
char type[GUID_STRLEN];
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, i);
const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
if (IsUnused(drive, ANY_VALID, i))
continue;
if (!params->numeric && guid) {
ResolveType(guid, type);
} else {
snprintf(type, sizeof(type), "MTD partition type %d",
MtdGetEntryType(entry));
}
printf(PARTITION_FMT, (int)entry->starting_lba,
(int)(entry->ending_lba - entry->starting_lba + 1),
i+1, type);
}
} else { // show all partitions
if (params->debug || params->verbose) {
char indent[64];
require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
MtdHeaderDetails(&drive->mtd.primary, indent, 0);
}
MtdEntriesDetails(drive, PRIMARY, params->numeric);
}
return CGPT_OK;
}
int GptShow(struct drive *drive, CgptShowParams *params) {
int gpt_retval;
if (params == NULL)
return CGPT_FAILED;
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
return CGPT_FAILED;
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) {
Error("GptSanityCheck() returned %d: %s\n",
gpt_retval, GptError(gpt_retval));
return CGPT_FAILED;
@@ -218,13 +333,13 @@ int CgptShow(CgptShowParams *params) {
if (params->partition) { // show single partition
if (params->partition > GetNumberOfEntries(&drive)) {
if (params->partition > GetNumberOfEntries(drive)) {
Error("invalid partition number: %d\n", params->partition);
return CGPT_FAILED;
}
uint32_t index = params->partition - 1;
GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, index);
GptEntry *entry = GetEntry(&drive->gpt, ANY_VALID, index);
char buf[256]; // scratch buffer for string conversion
if (params->single_item) {
@@ -254,13 +369,13 @@ int CgptShow(CgptShowParams *params) {
printf("%s\n", buf);
break;
case 'S':
printf("%d\n", GetSuccessful(&drive, ANY_VALID, index));
printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
break;
case 'T':
printf("%d\n", GetTries(&drive, ANY_VALID, index));
printf("%d\n", GetTries(drive, ANY_VALID, index));
break;
case 'P':
printf("%d\n", GetPriority(&drive, ANY_VALID, index));
printf("%d\n", GetPriority(drive, ANY_VALID, index));
break;
case 'A':
printf("0x%x\n", entry->attrs.fields.gpt_att);
@@ -276,8 +391,8 @@ int CgptShow(CgptShowParams *params) {
GptEntry *entry;
char type[GUID_STRLEN];
for (i = 0; i < GetNumberOfEntries(&drive); ++i) {
entry = GetEntry(&drive.gpt, ANY_VALID, i);
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
entry = GetEntry(&drive->gpt, ANY_VALID, i);
if (GuidIsZero(&entry->type))
continue;
@@ -293,17 +408,17 @@ int CgptShow(CgptShowParams *params) {
} else { // show all partitions
GptEntry *entries;
if (CGPT_OK != ReadPMBR(&drive)) {
if (CGPT_OK != ReadPMBR(drive)) {
Error("Unable to read PMBR\n");
return CGPT_FAILED;
}
printf(TITLE_FMT, "start", "size", "part", "contents");
char buf[256]; // buffer for formatted PMBR content
PMBRToStr(&drive.pmbr, buf, sizeof(buf)); // will exit if buf is too small
PMBRToStr(&drive->pmbr, buf, sizeof(buf)); // will exit if buf is too small
printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", buf);
if (drive.gpt.valid_headers & MASK_PRIMARY) {
if (drive->gpt.valid_headers & MASK_PRIMARY) {
printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
(int)GPT_HEADER_SECTOR, "", "Pri GPT header");
} else {
@@ -312,30 +427,30 @@ int CgptShow(CgptShowParams *params) {
}
if (params->debug ||
((drive.gpt.valid_headers & MASK_PRIMARY) && params->verbose)) {
((drive->gpt.valid_headers & MASK_PRIMARY) && params->verbose)) {
GptHeader *header;
char indent[64];
require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
header = (GptHeader*)drive.gpt.primary_header;
entries = (GptEntry*)drive.gpt.primary_entries;
header = (GptHeader*)drive->gpt.primary_header;
entries = (GptEntry*)drive->gpt.primary_entries;
HeaderDetails(header, entries, indent, params->numeric);
}
printf(GPT_FMT, (int)(GPT_PMBR_SECTOR + GPT_HEADER_SECTOR),
(int)GPT_ENTRIES_SECTORS,
drive.gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
"Pri GPT table");
if (params->debug ||
(drive.gpt.valid_entries & MASK_PRIMARY))
EntriesDetails(&drive, PRIMARY, params->numeric);
(drive->gpt.valid_entries & MASK_PRIMARY))
EntriesDetails(drive, PRIMARY, params->numeric);
/****************************** Secondary *************************/
printf(GPT_FMT, (int)(drive.gpt.drive_sectors - GPT_HEADER_SECTOR -
printf(GPT_FMT, (int)(drive->gpt.drive_sectors - GPT_HEADER_SECTOR -
GPT_ENTRIES_SECTORS),
(int)GPT_ENTRIES_SECTORS,
drive.gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
drive->gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
"Sec GPT table");
/* We show secondary table details if any of following is true.
* 1. in debug mode.
@@ -343,15 +458,15 @@ int CgptShow(CgptShowParams *params) {
* 3. secondary is not identical to promary.
*/
if (params->debug ||
((drive.gpt.valid_entries & MASK_SECONDARY) &&
(!(drive.gpt.valid_entries & MASK_PRIMARY) ||
memcmp(drive.gpt.primary_entries, drive.gpt.secondary_entries,
((drive->gpt.valid_entries & MASK_SECONDARY) &&
(!(drive->gpt.valid_entries & MASK_PRIMARY) ||
memcmp(drive->gpt.primary_entries, drive->gpt.secondary_entries,
TOTAL_ENTRIES_SIZE)))) {
EntriesDetails(&drive, SECONDARY, params->numeric);
EntriesDetails(drive, SECONDARY, params->numeric);
}
if (drive.gpt.valid_headers & MASK_SECONDARY)
printf(GPT_FMT, (int)(drive.gpt.drive_sectors - GPT_HEADER_SECTOR),
if (drive->gpt.valid_headers & MASK_SECONDARY)
printf(GPT_FMT, (int)(drive->gpt.drive_sectors - GPT_HEADER_SECTOR),
(int)GPT_HEADER_SECTOR, "", "Sec GPT header");
else
printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
@@ -362,23 +477,43 @@ int CgptShow(CgptShowParams *params) {
* 3. secondary is not synonymous to primary.
*/
if (params->debug ||
((drive.gpt.valid_headers & MASK_SECONDARY) &&
(!(drive.gpt.valid_headers & MASK_PRIMARY) ||
!IsSynonymous((GptHeader*)drive.gpt.primary_header,
(GptHeader*)drive.gpt.secondary_header)) &&
((drive->gpt.valid_headers & MASK_SECONDARY) &&
(!(drive->gpt.valid_headers & MASK_PRIMARY) ||
!IsSynonymous((GptHeader*)drive->gpt.primary_header,
(GptHeader*)drive->gpt.secondary_header)) &&
params->verbose)) {
GptHeader *header;
char indent[64];
require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
header = (GptHeader*)drive.gpt.secondary_header;
entries = (GptEntry*)drive.gpt.secondary_entries;
header = (GptHeader*)drive->gpt.secondary_header;
entries = (GptEntry*)drive->gpt.secondary_entries;
HeaderDetails(header, entries, indent, params->numeric);
}
}
CheckValid(&drive);
DriveClose(&drive, 0);
CheckValid(drive);
return CGPT_OK;
}
int CgptShow(CgptShowParams *params) {
struct drive drive;
if (params == NULL)
return CGPT_FAILED;
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
return CGPT_FAILED;
if (drive.is_mtd) {
if (MtdShow(&drive, params))
return CGPT_FAILED;
} else {
if (GptShow(&drive, params))
return CGPT_FAILED;
}
DriveClose(&drive, 0);
return CGPT_OK;
}