1a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* libs/diskconfig/diskconfig.c
2a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *
3a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Copyright 2008, The Android Open Source Project
4a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *
5a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Licensed under the Apache License, Version 2.0 (the "License");
6a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * you may not use this file except in compliance with the License.
7a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * You may obtain a copy of the License at
8a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *
9a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *     http://www.apache.org/licenses/LICENSE-2.0
10a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *
11a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Unless required by applicable law or agreed to in writing, software
12a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * distributed under the License is distributed on an "AS IS" BASIS,
13a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * See the License for the specific language governing permissions and
15a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * limitations under the License.
16a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */
17a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
18a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#define LOG_TAG "diskconfig"
19a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
20a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <errno.h>
21a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <fcntl.h>
22ccecf1425412beb2bc3bb38d470293fdc244d6f1Elliott Hughes#include <inttypes.h>
23a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <stdio.h>
24a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <stdlib.h>
25a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <string.h>
26a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <unistd.h>
27a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <sys/ioctl.h>
28a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <sys/stat.h>
29a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
30a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <linux/fs.h>
31a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
32a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <cutils/config_utils.h>
331874e6557cbaf36e6893e502d4cdd7c645444b8fMark Salyzyn#include <log/log.h>
34a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
35a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <diskconfig/diskconfig.h>
36a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
37a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
38a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic int
39a6391f1006b961ca89d1c79a826375380684a4deSan Mehatparse_len(const char *str, uint64_t *plen)
40a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
41a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    char tmp[64];
42a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int len_str;
43a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    uint32_t multiple = 1;
44a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
45a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    strncpy(tmp, str, sizeof(tmp));
46a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    tmp[sizeof(tmp)-1] = '\0';
47a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    len_str = strlen(tmp);
48a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!len_str) {
4901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Invalid disk length specified.");
50a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return 1;
51a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
52a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
53a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    switch(tmp[len_str - 1]) {
54a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case 'M': case 'm':
55a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            /* megabyte */
56a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            multiple <<= 10;
57a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case 'K': case 'k':
58a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            /* kilobytes */
59a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            multiple <<= 10;
60a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            tmp[len_str - 1] = '\0';
61a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
62a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        default:
63a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
64a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
65a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
66a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    *plen = strtoull(tmp, NULL, 0);
67a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!*plen) {
6801dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Invalid length specified: %s", str);
69a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return 1;
70a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
71a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
72a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (*plen == (uint64_t)-1) {
73a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (multiple > 1) {
7401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Size modifier illegal when len is -1");
75a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return 1;
76a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
77a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    } else {
78a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        /* convert len to kilobytes */
79a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (multiple > 1024)
80a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            multiple >>= 10;
81a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        *plen *= multiple;
82a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
83a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (*plen > 0xffffffffULL) {
84ccecf1425412beb2bc3bb38d470293fdc244d6f1Elliott Hughes            ALOGE("Length specified is too large!: %"PRIu64" KB", *plen);
85a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return 1;
86a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
87a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
88a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
89a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 0;
90a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
91a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
92a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
93a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic int
94a6391f1006b961ca89d1c79a826375380684a4deSan Mehatload_partitions(cnode *root, struct disk_info *dinfo)
95a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
96a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    cnode *partnode;
97a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
98a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    dinfo->num_parts = 0;
99a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    for (partnode = root->first_child; partnode; partnode = partnode->next) {
100a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        struct part_info *pinfo = &dinfo->part_lst[dinfo->num_parts];
101a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        const char *tmp;
102a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
103a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        /* bleh, i will leak memory here, but i DONT CARE since
104a6391f1006b961ca89d1c79a826375380684a4deSan Mehat         * the only right thing to do when this function fails
105a6391f1006b961ca89d1c79a826375380684a4deSan Mehat         * is to quit */
106a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        pinfo->name = strdup(partnode->name);
107a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
108a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if(config_bool(partnode, "active", 0))
109a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            pinfo->flags |= PART_ACTIVE_FLAG;
110a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
111a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!(tmp = config_str(partnode, "type", NULL))) {
11201dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Partition type required: %s", pinfo->name);
113a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return 1;
114a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
115a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
116a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        /* possible values are: linux, fat32 */
117a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!strcmp(tmp, "linux")) {
118a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            pinfo->type = PC_PART_TYPE_LINUX;
119a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        } else if (!strcmp(tmp, "fat32")) {
120a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            pinfo->type = PC_PART_TYPE_FAT32;
121a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        } else {
12201dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Unsupported partition type found: %s", tmp);
123a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return 1;
124a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
125a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
126a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if ((tmp = config_str(partnode, "len", NULL)) != NULL) {
127a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            uint64_t len;
128a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            if (parse_len(tmp, &len))
129a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                return 1;
130a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            pinfo->len_kb = (uint32_t) len;
131a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        } else
132a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            pinfo->len_kb = 0;
133a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
134a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        ++dinfo->num_parts;
135a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
136a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
137a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 0;
138a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
139a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
140a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstruct disk_info *
141a6391f1006b961ca89d1c79a826375380684a4deSan Mehatload_diskconfig(const char *fn, char *path_override)
142a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
143a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct disk_info *dinfo;
144a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    cnode *devroot;
145a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    cnode *partnode;
146a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    cnode *root = config_node("", "");
147a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    const char *tmp;
148a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
149a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(dinfo = malloc(sizeof(struct disk_info)))) {
15001dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Could not malloc disk_info");
151a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return NULL;
152a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
153a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    memset(dinfo, 0, sizeof(struct disk_info));
154a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
155a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(dinfo->part_lst = malloc(MAX_NUM_PARTS * sizeof(struct part_info)))) {
15601dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Could not malloc part_lst");
157a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
158a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
159a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    memset(dinfo->part_lst, 0,
160a6391f1006b961ca89d1c79a826375380684a4deSan Mehat           (MAX_NUM_PARTS * sizeof(struct part_info)));
161a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
162a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    config_load_file(root, fn);
163a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (root->first_child == NULL) {
16401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Could not read config file %s", fn);
165a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
166a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
167a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
168a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(devroot = config_find(root, "device"))) {
16901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Could not find device section in config file '%s'", fn);
170a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
171a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
172a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
173a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
174a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(tmp = config_str(devroot, "path", path_override))) {
17501dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("device path is requried");
176a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
177a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
178a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    dinfo->device = strdup(tmp);
179a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
180a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* find the partition scheme */
181a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(tmp = config_str(devroot, "scheme", NULL))) {
18201dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("partition scheme is required");
183a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
184a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    } else if (!strcmp(tmp, "mbr")) {
185a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        dinfo->scheme = PART_SCHEME_MBR;
186a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    } else if (!strcmp(tmp, "gpt")) {
18701dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("'gpt' partition scheme not supported yet.");
188a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
189a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    } else {
19001dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Unknown partition scheme specified: %s", tmp);
191a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
192a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
193a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
194a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* grab the sector size (in bytes) */
195a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    tmp = config_str(devroot, "sector_size", "512");
196a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    dinfo->sect_size = strtol(tmp, NULL, 0);
197a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!dinfo->sect_size) {
19801dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Invalid sector size: %s", tmp);
199a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
200a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
201a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
202a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* first lba where the partitions will start on disk */
203a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(tmp = config_str(devroot, "start_lba", NULL))) {
20401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("start_lba must be provided");
205a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
206a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
207a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
208a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(dinfo->skip_lba = strtol(tmp, NULL, 0))) {
20901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Invalid starting LBA (or zero): %s", tmp);
210a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
211a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
212a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
213a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* Number of LBAs on disk */
214a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(tmp = config_str(devroot, "num_lba", NULL))) {
21501dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("num_lba is required");
216a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
217a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
218a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    dinfo->num_lba = strtoul(tmp, NULL, 0);
219a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
220a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(partnode = config_find(devroot, "partitions"))) {
22101dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Device must specify partition list");
222a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
223a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
224a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
225a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (load_partitions(partnode, dinfo))
226a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
227a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
228a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return dinfo;
229a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
230a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfail:
231a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (dinfo->part_lst)
232a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        free(dinfo->part_lst);
233a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (dinfo->device)
234a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        free(dinfo->device);
235a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    free(dinfo);
236a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return NULL;
237a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
238a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
239a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic int
240a6391f1006b961ca89d1c79a826375380684a4deSan Mehatsync_ptable(int fd)
241a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
242a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct stat stat;
243a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int rv;
244a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
245a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    sync();
246a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
247a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (fstat(fd, &stat)) {
24801dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block       ALOGE("Cannot stat, errno=%d.", errno);
249a6391f1006b961ca89d1c79a826375380684a4deSan Mehat       return -1;
250a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
251a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
252a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (S_ISBLK(stat.st_mode) && ((rv = ioctl(fd, BLKRRPART, NULL)) < 0)) {
25301dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Could not re-read partition table. REBOOT!. (errno=%d)", errno);
254a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return -1;
255a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
256a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
257a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 0;
258a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
259a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
260a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* This function verifies that the disk info provided is valid, and if so,
261a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * returns an open file descriptor.
262a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *
263a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * This does not necessarily mean that it will later be successfully written
264a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * though. If we use the pc-bios partitioning scheme, we must use extended
265a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * partitions, which eat up some hd space. If the user manually provisioned
266a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * every single partition, but did not account for the extra needed space,
267a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * then we will later fail.
268a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *
269a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * TODO: Make validation more complete.
270a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */
271a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic int
272a6391f1006b961ca89d1c79a826375380684a4deSan Mehatvalidate(struct disk_info *dinfo)
273a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
274a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int fd;
275a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int sect_sz;
276a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    uint64_t disk_size;
277a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    uint64_t total_size;
278a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int cnt;
279a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct stat stat;
280a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
281a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!dinfo)
282a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return -1;
283a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
284a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if ((fd = open(dinfo->device, O_RDWR)) < 0) {
28501dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Cannot open device '%s' (errno=%d)", dinfo->device, errno);
286a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return -1;
287a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
288a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
289a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (fstat(fd, &stat)) {
29001dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Cannot stat file '%s', errno=%d.", dinfo->device, errno);
291a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
292a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
293a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
294a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
295a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* XXX: Some of the code below is kind of redundant and should probably
296a6391f1006b961ca89d1c79a826375380684a4deSan Mehat     * be refactored a little, but it will do for now. */
297a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
298a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* Verify that we can operate on the device that was requested.
299a6391f1006b961ca89d1c79a826375380684a4deSan Mehat     * We presently only support block devices and regular file images. */
300a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (S_ISBLK(stat.st_mode)) {
301a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        /* get the sector size and make sure we agree */
302a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (ioctl(fd, BLKSSZGET, &sect_sz) < 0) {
30301dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Cannot get sector size (errno=%d)", errno);
304a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
305a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
306a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
307a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!sect_sz || sect_sz != dinfo->sect_size) {
30801dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Device sector size is zero or sector sizes do not match!");
309a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
310a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
311a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
312a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        /* allow the user override the "disk size" if they provided num_lba */
313a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!dinfo->num_lba) {
314a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            if (ioctl(fd, BLKGETSIZE64, &disk_size) < 0) {
31501dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block                ALOGE("Could not get block device size (errno=%d)", errno);
316a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                goto fail;
317a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            }
318a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            /* XXX: we assume that the disk has < 2^32 sectors :-) */
319a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            dinfo->num_lba = (uint32_t)(disk_size / (uint64_t)dinfo->sect_size);
320a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        } else
321a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            disk_size = (uint64_t)dinfo->num_lba * (uint64_t)dinfo->sect_size;
322a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    } else if (S_ISREG(stat.st_mode)) {
323fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block        ALOGI("Requesting operation on a regular file, not block device.");
324a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!dinfo->sect_size) {
32501dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Sector size for regular file images cannot be zero");
326a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
327a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
328a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (dinfo->num_lba)
329a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            disk_size = (uint64_t)dinfo->num_lba * (uint64_t)dinfo->sect_size;
330a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        else {
331a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            dinfo->num_lba = (uint32_t)(stat.st_size / dinfo->sect_size);
332a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            disk_size = (uint64_t)stat.st_size;
333a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
334a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    } else {
33501dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Device does not refer to a regular file or a block device!");
336a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
337a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
338a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
339a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#if 1
3401874e6557cbaf36e6893e502d4cdd7c645444b8fMark Salyzyn    ALOGV("Device/file %s: size=%" PRIu64 " bytes, num_lba=%u, sect_size=%d",
341a6391f1006b961ca89d1c79a826375380684a4deSan Mehat         dinfo->device, disk_size, dinfo->num_lba, dinfo->sect_size);
342a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#endif
343a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
344a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* since this is our offset into the disk, we start off with that as
345a6391f1006b961ca89d1c79a826375380684a4deSan Mehat     * our size of needed partitions */
346a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    total_size = dinfo->skip_lba * dinfo->sect_size;
347a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
348a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* add up all the partition sizes and make sure it fits */
349a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    for (cnt = 0; cnt < dinfo->num_parts; ++cnt) {
350a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        struct part_info *part = &dinfo->part_lst[cnt];
351a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (part->len_kb != (uint32_t)-1) {
352a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            total_size += part->len_kb * 1024;
353a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        } else if (part->len_kb == 0) {
35401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Zero-size partition '%s' is invalid.", part->name);
355a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
356a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        } else {
357a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            /* the partition requests the rest of the disk. */
358a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            if (cnt + 1 != dinfo->num_parts) {
35901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block                ALOGE("Only the last partition in the list can request to fill "
360a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                     "the rest of disk.");
361a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                goto fail;
362a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            }
363a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
364a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
365a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if ((part->type != PC_PART_TYPE_LINUX) &&
366a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            (part->type != PC_PART_TYPE_FAT32)) {
36701dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Unknown partition type (0x%x) encountered for partition "
368a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                 "'%s'\n", part->type, part->name);
369a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
370a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
371a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
372a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
373a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* only matters for disks, not files */
374a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (S_ISBLK(stat.st_mode) && total_size > disk_size) {
375ccecf1425412beb2bc3bb38d470293fdc244d6f1Elliott Hughes        ALOGE("Total requested size of partitions (%"PRIu64") is greater than disk "
376ccecf1425412beb2bc3bb38d470293fdc244d6f1Elliott Hughes             "size (%"PRIu64").", total_size, disk_size);
377a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
378a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
379a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
380a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return fd;
381a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
382a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfail:
383a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    close(fd);
384a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return -1;
385a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
386a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
387a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic int
388a6391f1006b961ca89d1c79a826375380684a4deSan Mehatvalidate_and_config(struct disk_info *dinfo, int *fd, struct write_list **lst)
389a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
390a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    *lst = NULL;
391a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    *fd = -1;
392a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
393a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if ((*fd = validate(dinfo)) < 0)
394a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return 1;
395a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
396a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    switch (dinfo->scheme) {
397a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case PART_SCHEME_MBR:
398a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            *lst = config_mbr(dinfo);
399a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return *lst == NULL;
400a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case PART_SCHEME_GPT:
401a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            /* not supported yet */
402a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        default:
40301dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Uknown partition scheme.");
404a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
405a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
406a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
407a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    close(*fd);
408a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    *lst = NULL;
409a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 1;
410a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
411a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
412a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* validate and process the disk layout configuration.
413a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * This will cause an update to the partitions' start lba.
414a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *
415a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Basically, this does the same thing as apply_disk_config in test mode,
416a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * except that wlist_commit is not called to print out the data to be
417a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * written.
418a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */
419a6391f1006b961ca89d1c79a826375380684a4deSan Mehatint
420a6391f1006b961ca89d1c79a826375380684a4deSan Mehatprocess_disk_config(struct disk_info *dinfo)
421a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
422a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct write_list *lst;
423a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int fd;
424a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
425a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (validate_and_config(dinfo, &fd, &lst) != 0)
426a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return 1;
427a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
428a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    close(fd);
429a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    wlist_free(lst);
430a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 0;
431a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
432a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
433a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
434a6391f1006b961ca89d1c79a826375380684a4deSan Mehatint
435a6391f1006b961ca89d1c79a826375380684a4deSan Mehatapply_disk_config(struct disk_info *dinfo, int test)
436a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
437a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int fd;
438a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct write_list *wr_lst = NULL;
439a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int rv;
440a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
441a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (validate_and_config(dinfo, &fd, &wr_lst) != 0) {
44201dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Configuration is invalid.");
443a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
444a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
445a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
446a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if ((rv = wlist_commit(fd, wr_lst, test)) >= 0)
447a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        rv = test ? 0 : sync_ptable(fd);
448a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
449a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    close(fd);
450a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    wlist_free(wr_lst);
451a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return rv;
452a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
453a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfail:
454a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    close(fd);
455a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (wr_lst)
456a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        wlist_free(wr_lst);
457a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 1;
458a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
459a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
460a6391f1006b961ca89d1c79a826375380684a4deSan Mehatint
461a6391f1006b961ca89d1c79a826375380684a4deSan Mehatdump_disk_config(struct disk_info *dinfo)
462a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
463a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int cnt;
464a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct part_info *part;
465a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
466a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Device: %s\n", dinfo->device);
467a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Scheme: ");
468a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    switch (dinfo->scheme) {
469a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case PART_SCHEME_MBR:
470a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            printf("MBR");
471a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
472a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case PART_SCHEME_GPT:
473a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            printf("GPT (unsupported)");
474a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
475a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        default:
476a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            printf("Unknown");
477a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
478a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
479a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf ("\n");
480a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
481a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Sector size: %d\n", dinfo->sect_size);
482a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Skip leading LBAs: %u\n", dinfo->skip_lba);
483a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Number of LBAs: %u\n", dinfo->num_lba);
484a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Partitions:\n");
485a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
486a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    for (cnt = 0; cnt < dinfo->num_parts; ++cnt) {
487a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        part = &dinfo->part_lst[cnt];
488a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        printf("\tname = %s\n", part->name);
489a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        printf("\t\tflags = %s\n",
490a6391f1006b961ca89d1c79a826375380684a4deSan Mehat               part->flags & PART_ACTIVE_FLAG ? "Active" : "None");
491a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        printf("\t\ttype = %s\n",
492a6391f1006b961ca89d1c79a826375380684a4deSan Mehat               part->type == PC_PART_TYPE_LINUX ? "Linux" : "Unknown");
493a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (part->len_kb == (uint32_t)-1)
494a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            printf("\t\tlen = rest of disk\n");
495a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        else
496a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            printf("\t\tlen = %uKB\n", part->len_kb);
497a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
498a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Total number of partitions: %d\n", cnt);
499a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("\n");
500a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
501a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 0;
502a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
503a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
504a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstruct part_info *
505a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfind_part(struct disk_info *dinfo, const char *name)
506a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
507a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct part_info *pinfo;
508a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int cnt;
509a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
510a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    for (cnt = 0; cnt < dinfo->num_parts; ++cnt) {
511a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        pinfo = &dinfo->part_lst[cnt];
512a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!strcmp(pinfo->name, name))
513a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return pinfo;
514a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
515a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
516a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return NULL;
517a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
518a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
519a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* NOTE: If the returned ptr is non-NULL, it must be freed by the caller. */
520a6391f1006b961ca89d1c79a826375380684a4deSan Mehatchar *
521a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfind_part_device(struct disk_info *dinfo, const char *name)
522a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
523a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    switch (dinfo->scheme) {
524a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case PART_SCHEME_MBR:
525a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return find_mbr_part(dinfo, name);
526a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case PART_SCHEME_GPT:
52701dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("GPT is presently not supported");
528a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
529a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        default:
53001dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Unknown partition table scheme");
531a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
532a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
533a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
534a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return NULL;
535a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
536a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
537a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
538