1a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// Use of this source code is governed by a BSD-style license that can be
3a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// found in the LICENSE file.
4a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
5a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#include <string.h>
6a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#include <sys/stat.h>
7a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#include <sys/types.h>
8f47291926afce3235421f73811a04324195f3e13Bill Richardson#include <unistd.h>
9a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
10f47291926afce3235421f73811a04324195f3e13Bill Richardson#include "cgpt.h"
11d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen#include "cgpt_nor.h"
12f47291926afce3235421f73811a04324195f3e13Bill Richardson#include "cgptlib_internal.h"
130c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "vboot_host.h"
14a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
15a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#define BUFSIZE 1024
16a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// FIXME: currently we only support 512-byte sectors.
17a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#define LBA_SIZE 512
18a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
19a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
20a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// fill comparebuf with the data to be examined, returning true on success.
21250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasanstatic int FillBuffer(CgptFindParams *params, int fd, uint64_t pos,
22a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                       uint64_t count) {
23a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  uint8_t *bufptr = params->comparebuf;
24a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
25a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  if (-1 == lseek(fd, pos, SEEK_SET))
26a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    return 0;
27a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
28a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  // keep reading until done or error
29a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  while (count) {
30a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    ssize_t bytes_read = read(fd, bufptr, count);
31a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    // negative means error, 0 means (unexpected) EOF
32a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    if (bytes_read <= 0)
33a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      return 0;
34a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    count -= bytes_read;
35a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    bufptr += bytes_read;
36a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
37a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
38a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  return 1;
39a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
40a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
41a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// check partition data content. return true for match, 0 for no match or error
42250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasanstatic int match_content(CgptFindParams *params, struct drive *drive,
43a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                             GptEntry *entry) {
44a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  uint64_t part_size;
45a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
46a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  if (!params->matchlen)
47a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    return 1;
48a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
49a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  // Ensure that the region we want to match against is inside the partition.
50a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  part_size = LBA_SIZE * (entry->ending_lba - entry->starting_lba + 1);
51a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  if (params->matchoffset + params->matchlen > part_size) {
52a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    return 0;
53a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
54a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
55a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  // Read the partition data.
56a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  if (!FillBuffer(params,
57a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                  drive->fd,
58a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                  (LBA_SIZE * entry->starting_lba) + params->matchoffset,
59a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                  params->matchlen)) {
60a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    Error("unable to read partition data\n");
61a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    return 0;
62a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
63a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
64a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  // Compare it
65a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  if (0 == memcmp(params->matchbuf, params->comparebuf, params->matchlen)) {
66a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    return 1;
67a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
68a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
69a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  // Nope.
70a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  return 0;
71a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
72a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
73a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3, /dev/sda -> /dev/sda3
74250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasanstatic void showmatch(CgptFindParams *params, char *filename,
75549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen                      int partnum, GptEntry *entry) {
76a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  char * format = "%s%d\n";
77a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  if (strncmp("/dev/mmcblk", filename, 11) == 0)
78a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    format = "%sp%d\n";
79549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen
80549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen  if (params->numeric) {
81a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    printf("%d\n", partnum);
82549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen  } else {
83549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen    if (params->show_fn) {
84549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen      params->show_fn(params, filename, partnum, entry);
85549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen    } else {
86549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen      printf(format, filename, partnum);
87549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen    }
88549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen  }
89a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  if (params->verbose > 0)
90a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    EntryDetails(entry, partnum - 1, params->numeric);
91a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
92a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
93549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen// This handles the MTD devices. ChromeOS uses /dev/mtdX for kernel partitions,
94549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen// /dev/ubiblockX_0 for root partitions, and /dev/ubiX for stateful partition.
95549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyenstatic void chromeos_mtd_show(CgptFindParams *params, char *filename,
96549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen                              int partnum, GptEntry *entry) {
97549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen  if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
98549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen    printf("/dev/mtd%d\n", partnum);
99549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen  } else if (GuidEqual(&guid_chromeos_rootfs, &entry->type)) {
100549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen    printf("/dev/ubiblock%d_0\n", partnum);
101549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen  } else {
102549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen    printf("/dev/ubi%d_0\n", partnum);
103549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen  }
104549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen}
105549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen
106a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// This returns true if a GPT partition matches the search criteria. If a match
107a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// isn't found (or if the file doesn't contain a GPT), it returns false. The
108a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// filename and partition number that matched is left in a global, since we
109a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// could have multiple hits.
1101c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulkstatic int gpt_search(CgptFindParams *params, struct drive *drive,
1111c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk                      char *filename) {
112a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  int i;
113a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  GptEntry *entry;
1141c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  int retval = 0;
115a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  char partlabel[GPT_PARTNAME_LEN];
116a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
1171c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  if (GPT_SUCCESS != GptSanityCheck(&drive->gpt)) {
118a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    return 0;
119a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
120a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
1211c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  for (i = 0; i < GetNumberOfEntries(drive); ++i) {
1221c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    entry = GetEntry(&drive->gpt, ANY_VALID, i);
123a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
1243f806a2abf07d7b801852a4a6f3a9080a4b5c427Bill Richardson    if (GuidIsZero(&entry->type))
125a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      continue;
126a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
127a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    int found = 0;
128a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    if ((params->set_unique && GuidEqual(&params->unique_guid, &entry->unique))
129a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        || (params->set_type && GuidEqual(&params->type_guid, &entry->type))) {
130a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      found = 1;
131a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    } else if (params->set_label) {
132a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      if (CGPT_OK != UTF16ToUTF8(entry->name,
133a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                                 sizeof(entry->name) / sizeof(entry->name[0]),
134a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                                 (uint8_t *)partlabel, sizeof(partlabel))) {
135a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        Error("The label cannot be converted from UTF16, so abort.\n");
136a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        return 0;
137a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      }
138a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      if (!strncmp(params->label, partlabel, sizeof(partlabel)))
139a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        found = 1;
140a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    }
1411c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    if (found && match_content(params, drive, entry)) {
142a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      params->hits++;
143a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      retval++;
1441c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk      showmatch(params, filename, i+1, entry);
145a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      if (!params->match_partnum)
146a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        params->match_partnum = i+1;
147a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    }
148a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
149a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
1501c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  return retval;
1511c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk}
1521c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk
1531c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulkstatic int do_search(CgptFindParams *params, char *fileName) {
1541c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  int retval;
1551c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  struct drive drive;
1561c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk
157ab899591808dd3e5f955ab7693b54a83389cd35fNam T. Nguyen  if (CGPT_OK != DriveOpen(fileName, &drive, O_RDONLY, params->drive_size))
1581c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    return 0;
1591c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk
1608577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen  retval = gpt_search(params, &drive, fileName);
1611c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk
162a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  (void) DriveClose(&drive, 0);
163a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
164a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  return retval;
165a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
166a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
167a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
168d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen#define PROC_MTD "/proc/mtd"
169a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#define PROC_PARTITIONS "/proc/partitions"
170a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#define DEV_DIR "/dev"
171a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#define SYS_BLOCK_DIR "/sys/block"
172a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
173a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasanstatic const char *devdirs[] = { "/dev", "/devices", "/devfs", 0 };
174a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
175a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// Given basename "foo", see if we can find a whole, real device by that name.
176a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// This is copied from the logic in the linux utility 'findfs', although that
177a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// does more exhaustive searching.
178a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasanstatic char *is_wholedev(const char *basename) {
179a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  int i;
180a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  struct stat statbuf;
181a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  static char pathname[BUFSIZE];        // we'll return this.
182a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  char tmpname[BUFSIZE];
183a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
184a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  // It should be a block device under /dev/,
185a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  for (i = 0; devdirs[i]; i++) {
186a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    sprintf(pathname, "%s/%s", devdirs[i], basename);
187a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
188a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    if (0 != stat(pathname, &statbuf))
189a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      continue;
190a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
191a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    if (!S_ISBLK(statbuf.st_mode))
192a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      continue;
193a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
194a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    // It should have a symlink called /sys/block/*/device
195a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    sprintf(tmpname, "%s/%s/device", SYS_BLOCK_DIR, basename);
196a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
197a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    if (0 != lstat(tmpname, &statbuf))
198a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      continue;
199a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
200a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    if (!S_ISLNK(statbuf.st_mode))
201a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      continue;
202a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
203a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    // found it
204a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    return pathname;
205a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
206a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
207a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  return 0;
208a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
209a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
210a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// This scans all the physical devices it can find, looking for a match. It
211a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// returns true if any matches were found, false otherwise.
212a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasanstatic int scan_real_devs(CgptFindParams *params) {
213a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  int found = 0;
214a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  char partname[128];                   // max size for /proc/partition lines?
215a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  FILE *fp;
216a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  char *pathname;
217a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
218d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen  fp = fopen(PROC_PARTITIONS, "re");
219a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  if (!fp) {
220a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    perror("can't read " PROC_PARTITIONS);
221a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    return found;
222a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
223a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
224d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen  size_t line_length = 0;
225d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen  char *line = NULL;
226d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen  while (getline(&line, &line_length, fp) != -1) {
227a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    int ma, mi;
228a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    long long unsigned int sz;
229a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
230a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    if (sscanf(line, " %d %d %llu %127[^\n ]", &ma, &mi, &sz, partname) != 4)
231a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      continue;
232a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
233a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    if ((pathname = is_wholedev(partname))) {
234a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      if (do_search(params, pathname)) {
235a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        found++;
236a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      }
237a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    }
238a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
239a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
240a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  fclose(fp);
241d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen
242d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen  fp = fopen(PROC_MTD, "re");
243d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen  if (!fp) {
244d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen    free(line);
245d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen    return found;
246d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen  }
247d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen
248d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen  while (getline(&line, &line_length, fp) != -1) {
249d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen    uint64_t sz;
250d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen    uint32_t erasesz;
251d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen    char name[128];
252d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen    // dev:  size  erasesize  name
253d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen    if (sscanf(line, "%64[^:]: %" PRIx64 " %x \"%127[^\"]\"",
254d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen               partname, &sz, &erasesz, name) != 4)
255d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen      continue;
256d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen    if (strcmp(partname, "mtd0") == 0) {
257d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen      char temp_dir[] = "/tmp/cgpt_find.XXXXXX";
258d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen      if (params->drive_size == 0) {
259d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen        if (GetMtdSize("/dev/mtd0", &params->drive_size) != 0) {
260d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen          perror("GetMtdSize");
261d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen          goto cleanup;
262d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen        }
263d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen      }
264d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen      if (ReadNorFlash(temp_dir) != 0) {
265d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen        perror("ReadNorFlash");
266d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen        goto cleanup;
267d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen      }
268d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen      char nor_file[64];
269d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen      if (snprintf(nor_file, sizeof(nor_file), "%s/rw_gpt", temp_dir) > 0) {
270549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen        params->show_fn = chromeos_mtd_show;
271d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen        if (do_search(params, nor_file)) {
272d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen          found++;
273d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen        }
274549205787527d85dead8968af7a1e1064cafa00eNam T. Nguyen        params->show_fn = NULL;
275d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen      }
276d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen      RemoveDir(temp_dir);
277d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen      break;
278d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen    }
279d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen  }
280d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyencleanup:
281d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen  fclose(fp);
282d1236e4be6a7fe1c2b132ca8f63a513949d59775Nam T. Nguyen  free(line);
283a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  return found;
284a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
285a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
286a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
2873f806a2abf07d7b801852a4a6f3a9080a4b5c427Bill Richardsonvoid CgptFind(CgptFindParams *params) {
288a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  if (params == NULL)
289a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    return;
290a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
291250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan  if (params->drive_name != NULL)
292250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan    do_search(params, params->drive_name);
293a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  else
294a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    scan_real_devs(params);
295a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
296