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>
22a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <stdio.h>
23a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <stdlib.h>
24a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <string.h>
25a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <unistd.h>
26a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <sys/ioctl.h>
27a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <sys/stat.h>
28a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
29a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <linux/fs.h>
30a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
31a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <cutils/config_utils.h>
32a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <cutils/log.h>
33a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
34a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <diskconfig/diskconfig.h>
35a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
36a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
37a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic int
38a6391f1006b961ca89d1c79a826375380684a4deSan Mehatparse_len(const char *str, uint64_t *plen)
39a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
40a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    char tmp[64];
41a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int len_str;
42a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    uint32_t multiple = 1;
43a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
44a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    strncpy(tmp, str, sizeof(tmp));
45a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    tmp[sizeof(tmp)-1] = '\0';
46a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    len_str = strlen(tmp);
47a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!len_str) {
4801dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Invalid disk length specified.");
49a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return 1;
50a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
51a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
52a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    switch(tmp[len_str - 1]) {
53a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case 'M': case 'm':
54a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            /* megabyte */
55a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            multiple <<= 10;
56a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case 'K': case 'k':
57a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            /* kilobytes */
58a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            multiple <<= 10;
59a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            tmp[len_str - 1] = '\0';
60a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
61a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        default:
62a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
63a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
64a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
65a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    *plen = strtoull(tmp, NULL, 0);
66a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!*plen) {
6701dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Invalid length specified: %s", str);
68a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return 1;
69a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
70a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
71a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (*plen == (uint64_t)-1) {
72a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (multiple > 1) {
7301dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Size modifier illegal when len is -1");
74a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return 1;
75a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
76a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    } else {
77a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        /* convert len to kilobytes */
78a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (multiple > 1024)
79a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            multiple >>= 10;
80a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        *plen *= multiple;
81a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
82a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (*plen > 0xffffffffULL) {
8301dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Length specified is too large!: %llu KB", *plen);
84a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return 1;
85a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
86a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
87a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
88a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 0;
89a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
90a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
91a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
92a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic int
93a6391f1006b961ca89d1c79a826375380684a4deSan Mehatload_partitions(cnode *root, struct disk_info *dinfo)
94a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
95a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    cnode *partnode;
96a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
97a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    dinfo->num_parts = 0;
98a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    for (partnode = root->first_child; partnode; partnode = partnode->next) {
99a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        struct part_info *pinfo = &dinfo->part_lst[dinfo->num_parts];
100a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        const char *tmp;
101a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
102a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        /* bleh, i will leak memory here, but i DONT CARE since
103a6391f1006b961ca89d1c79a826375380684a4deSan Mehat         * the only right thing to do when this function fails
104a6391f1006b961ca89d1c79a826375380684a4deSan Mehat         * is to quit */
105a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        pinfo->name = strdup(partnode->name);
106a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
107a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if(config_bool(partnode, "active", 0))
108a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            pinfo->flags |= PART_ACTIVE_FLAG;
109a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
110a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!(tmp = config_str(partnode, "type", NULL))) {
11101dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Partition type required: %s", pinfo->name);
112a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return 1;
113a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
114a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
115a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        /* possible values are: linux, fat32 */
116a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!strcmp(tmp, "linux")) {
117a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            pinfo->type = PC_PART_TYPE_LINUX;
118a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        } else if (!strcmp(tmp, "fat32")) {
119a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            pinfo->type = PC_PART_TYPE_FAT32;
120a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        } else {
12101dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Unsupported partition type found: %s", tmp);
122a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return 1;
123a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
124a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
125a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if ((tmp = config_str(partnode, "len", NULL)) != NULL) {
126a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            uint64_t len;
127a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            if (parse_len(tmp, &len))
128a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                return 1;
129a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            pinfo->len_kb = (uint32_t) len;
130a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        } else
131a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            pinfo->len_kb = 0;
132a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
133a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        ++dinfo->num_parts;
134a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
135a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
136a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 0;
137a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
138a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
139a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstruct disk_info *
140a6391f1006b961ca89d1c79a826375380684a4deSan Mehatload_diskconfig(const char *fn, char *path_override)
141a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
142a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct disk_info *dinfo;
143a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    cnode *devroot;
144a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    cnode *partnode;
145a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    cnode *root = config_node("", "");
146a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    const char *tmp;
147a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
148a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(dinfo = malloc(sizeof(struct disk_info)))) {
14901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Could not malloc disk_info");
150a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return NULL;
151a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
152a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    memset(dinfo, 0, sizeof(struct disk_info));
153a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
154a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(dinfo->part_lst = malloc(MAX_NUM_PARTS * sizeof(struct part_info)))) {
15501dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Could not malloc part_lst");
156a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
157a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
158a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    memset(dinfo->part_lst, 0,
159a6391f1006b961ca89d1c79a826375380684a4deSan Mehat           (MAX_NUM_PARTS * sizeof(struct part_info)));
160a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
161a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    config_load_file(root, fn);
162a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (root->first_child == NULL) {
16301dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Could not read config file %s", fn);
164a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
165a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
166a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
167a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(devroot = config_find(root, "device"))) {
16801dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Could not find device section in config file '%s'", fn);
169a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
170a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
171a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
172a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
173a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(tmp = config_str(devroot, "path", path_override))) {
17401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("device path is requried");
175a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
176a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
177a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    dinfo->device = strdup(tmp);
178a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
179a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* find the partition scheme */
180a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(tmp = config_str(devroot, "scheme", NULL))) {
18101dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("partition scheme is required");
182a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
183a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    } else if (!strcmp(tmp, "mbr")) {
184a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        dinfo->scheme = PART_SCHEME_MBR;
185a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    } else if (!strcmp(tmp, "gpt")) {
18601dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("'gpt' partition scheme not supported yet.");
187a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
188a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    } else {
18901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Unknown partition scheme specified: %s", tmp);
190a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
191a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
192a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
193a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* grab the sector size (in bytes) */
194a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    tmp = config_str(devroot, "sector_size", "512");
195a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    dinfo->sect_size = strtol(tmp, NULL, 0);
196a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!dinfo->sect_size) {
19701dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Invalid sector size: %s", tmp);
198a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
199a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
200a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
201a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* first lba where the partitions will start on disk */
202a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(tmp = config_str(devroot, "start_lba", NULL))) {
20301dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("start_lba must be provided");
204a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
205a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
206a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
207a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(dinfo->skip_lba = strtol(tmp, NULL, 0))) {
20801dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Invalid starting LBA (or zero): %s", tmp);
209a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
210a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
211a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
212a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* Number of LBAs on disk */
213a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(tmp = config_str(devroot, "num_lba", NULL))) {
21401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("num_lba is required");
215a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
216a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
217a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    dinfo->num_lba = strtoul(tmp, NULL, 0);
218a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
219a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!(partnode = config_find(devroot, "partitions"))) {
22001dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Device must specify partition list");
221a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
222a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
223a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
224a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (load_partitions(partnode, dinfo))
225a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
226a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
227a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return dinfo;
228a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
229a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfail:
230a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (dinfo->part_lst)
231a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        free(dinfo->part_lst);
232a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (dinfo->device)
233a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        free(dinfo->device);
234a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    free(dinfo);
235a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return NULL;
236a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
237a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
238a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic int
239a6391f1006b961ca89d1c79a826375380684a4deSan Mehatsync_ptable(int fd)
240a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
241a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct stat stat;
242a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int rv;
243a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
244a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    sync();
245a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
246a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (fstat(fd, &stat)) {
24701dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block       ALOGE("Cannot stat, errno=%d.", errno);
248a6391f1006b961ca89d1c79a826375380684a4deSan Mehat       return -1;
249a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
250a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
251a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (S_ISBLK(stat.st_mode) && ((rv = ioctl(fd, BLKRRPART, NULL)) < 0)) {
25201dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Could not re-read partition table. REBOOT!. (errno=%d)", errno);
253a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return -1;
254a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
255a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
256a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 0;
257a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
258a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
259a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* This function verifies that the disk info provided is valid, and if so,
260a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * returns an open file descriptor.
261a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *
262a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * This does not necessarily mean that it will later be successfully written
263a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * though. If we use the pc-bios partitioning scheme, we must use extended
264a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * partitions, which eat up some hd space. If the user manually provisioned
265a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * every single partition, but did not account for the extra needed space,
266a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * then we will later fail.
267a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *
268a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * TODO: Make validation more complete.
269a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */
270a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic int
271a6391f1006b961ca89d1c79a826375380684a4deSan Mehatvalidate(struct disk_info *dinfo)
272a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
273a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int fd;
274a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int sect_sz;
275a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    uint64_t disk_size;
276a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    uint64_t total_size;
277a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int cnt;
278a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct stat stat;
279a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
280a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!dinfo)
281a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return -1;
282a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
283a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if ((fd = open(dinfo->device, O_RDWR)) < 0) {
28401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Cannot open device '%s' (errno=%d)", dinfo->device, errno);
285a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return -1;
286a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
287a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
288a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (fstat(fd, &stat)) {
28901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Cannot stat file '%s', errno=%d.", dinfo->device, errno);
290a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
291a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
292a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
293a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
294a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* XXX: Some of the code below is kind of redundant and should probably
295a6391f1006b961ca89d1c79a826375380684a4deSan Mehat     * be refactored a little, but it will do for now. */
296a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
297a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* Verify that we can operate on the device that was requested.
298a6391f1006b961ca89d1c79a826375380684a4deSan Mehat     * We presently only support block devices and regular file images. */
299a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (S_ISBLK(stat.st_mode)) {
300a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        /* get the sector size and make sure we agree */
301a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (ioctl(fd, BLKSSZGET, &sect_sz) < 0) {
30201dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Cannot get sector size (errno=%d)", errno);
303a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
304a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
305a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
306a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!sect_sz || sect_sz != dinfo->sect_size) {
30701dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Device sector size is zero or sector sizes do not match!");
308a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
309a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
310a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
311a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        /* allow the user override the "disk size" if they provided num_lba */
312a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!dinfo->num_lba) {
313a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            if (ioctl(fd, BLKGETSIZE64, &disk_size) < 0) {
31401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block                ALOGE("Could not get block device size (errno=%d)", errno);
315a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                goto fail;
316a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            }
317a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            /* XXX: we assume that the disk has < 2^32 sectors :-) */
318a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            dinfo->num_lba = (uint32_t)(disk_size / (uint64_t)dinfo->sect_size);
319a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        } else
320a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            disk_size = (uint64_t)dinfo->num_lba * (uint64_t)dinfo->sect_size;
321a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    } else if (S_ISREG(stat.st_mode)) {
322fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block        ALOGI("Requesting operation on a regular file, not block device.");
323a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!dinfo->sect_size) {
32401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Sector size for regular file images cannot be zero");
325a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
326a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
327a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (dinfo->num_lba)
328a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            disk_size = (uint64_t)dinfo->num_lba * (uint64_t)dinfo->sect_size;
329a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        else {
330a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            dinfo->num_lba = (uint32_t)(stat.st_size / dinfo->sect_size);
331a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            disk_size = (uint64_t)stat.st_size;
332a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
333a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    } else {
33401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Device does not refer to a regular file or a block device!");
335a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
336a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
337a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
338a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#if 1
33969f4cd7f5add7a7c7f5915e5292aab7eb2a42e9fSteve Block    ALOGV("Device/file %s: size=%llu bytes, num_lba=%u, sect_size=%d",
340a6391f1006b961ca89d1c79a826375380684a4deSan Mehat         dinfo->device, disk_size, dinfo->num_lba, dinfo->sect_size);
341a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#endif
342a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
343a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* since this is our offset into the disk, we start off with that as
344a6391f1006b961ca89d1c79a826375380684a4deSan Mehat     * our size of needed partitions */
345a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    total_size = dinfo->skip_lba * dinfo->sect_size;
346a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
347a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* add up all the partition sizes and make sure it fits */
348a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    for (cnt = 0; cnt < dinfo->num_parts; ++cnt) {
349a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        struct part_info *part = &dinfo->part_lst[cnt];
350a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (part->len_kb != (uint32_t)-1) {
351a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            total_size += part->len_kb * 1024;
352a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        } else if (part->len_kb == 0) {
35301dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Zero-size partition '%s' is invalid.", part->name);
354a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
355a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        } else {
356a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            /* the partition requests the rest of the disk. */
357a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            if (cnt + 1 != dinfo->num_parts) {
35801dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block                ALOGE("Only the last partition in the list can request to fill "
359a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                     "the rest of disk.");
360a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                goto fail;
361a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            }
362a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
363a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
364a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if ((part->type != PC_PART_TYPE_LINUX) &&
365a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            (part->type != PC_PART_TYPE_FAT32)) {
36601dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Unknown partition type (0x%x) encountered for partition "
367a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                 "'%s'\n", part->type, part->name);
368a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
369a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
370a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
371a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
372a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    /* only matters for disks, not files */
373a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (S_ISBLK(stat.st_mode) && total_size > disk_size) {
37401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Total requested size of partitions (%llu) is greater than disk "
375a6391f1006b961ca89d1c79a826375380684a4deSan Mehat             "size (%llu).", total_size, disk_size);
376a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
377a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
378a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
379a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return fd;
380a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
381a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfail:
382a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    close(fd);
383a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return -1;
384a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
385a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
386a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic int
387a6391f1006b961ca89d1c79a826375380684a4deSan Mehatvalidate_and_config(struct disk_info *dinfo, int *fd, struct write_list **lst)
388a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
389a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    *lst = NULL;
390a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    *fd = -1;
391a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
392a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if ((*fd = validate(dinfo)) < 0)
393a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return 1;
394a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
395a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    switch (dinfo->scheme) {
396a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case PART_SCHEME_MBR:
397a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            *lst = config_mbr(dinfo);
398a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return *lst == NULL;
399a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case PART_SCHEME_GPT:
400a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            /* not supported yet */
401a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        default:
40201dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Uknown partition scheme.");
403a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
404a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
405a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
406a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    close(*fd);
407a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    *lst = NULL;
408a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 1;
409a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
410a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
411a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* validate and process the disk layout configuration.
412a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * This will cause an update to the partitions' start lba.
413a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *
414a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Basically, this does the same thing as apply_disk_config in test mode,
415a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * except that wlist_commit is not called to print out the data to be
416a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * written.
417a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */
418a6391f1006b961ca89d1c79a826375380684a4deSan Mehatint
419a6391f1006b961ca89d1c79a826375380684a4deSan Mehatprocess_disk_config(struct disk_info *dinfo)
420a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
421a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct write_list *lst;
422a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int fd;
423a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
424a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (validate_and_config(dinfo, &fd, &lst) != 0)
425a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        return 1;
426a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
427a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    close(fd);
428a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    wlist_free(lst);
429a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 0;
430a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
431a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
432a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
433a6391f1006b961ca89d1c79a826375380684a4deSan Mehatint
434a6391f1006b961ca89d1c79a826375380684a4deSan Mehatapply_disk_config(struct disk_info *dinfo, int test)
435a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
436a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int fd;
437a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct write_list *wr_lst = NULL;
438a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int rv;
439a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
440a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (validate_and_config(dinfo, &fd, &wr_lst) != 0) {
44101dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Configuration is invalid.");
442a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
443a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
444a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
445a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if ((rv = wlist_commit(fd, wr_lst, test)) >= 0)
446a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        rv = test ? 0 : sync_ptable(fd);
447a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
448a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    close(fd);
449a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    wlist_free(wr_lst);
450a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return rv;
451a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
452a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfail:
453a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    close(fd);
454a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (wr_lst)
455a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        wlist_free(wr_lst);
456a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 1;
457a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
458a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
459a6391f1006b961ca89d1c79a826375380684a4deSan Mehatint
460a6391f1006b961ca89d1c79a826375380684a4deSan Mehatdump_disk_config(struct disk_info *dinfo)
461a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
462a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int cnt;
463a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct part_info *part;
464a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
465a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Device: %s\n", dinfo->device);
466a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Scheme: ");
467a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    switch (dinfo->scheme) {
468a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case PART_SCHEME_MBR:
469a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            printf("MBR");
470a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
471a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case PART_SCHEME_GPT:
472a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            printf("GPT (unsupported)");
473a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
474a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        default:
475a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            printf("Unknown");
476a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
477a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
478a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf ("\n");
479a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
480a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Sector size: %d\n", dinfo->sect_size);
481a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Skip leading LBAs: %u\n", dinfo->skip_lba);
482a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Number of LBAs: %u\n", dinfo->num_lba);
483a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Partitions:\n");
484a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
485a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    for (cnt = 0; cnt < dinfo->num_parts; ++cnt) {
486a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        part = &dinfo->part_lst[cnt];
487a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        printf("\tname = %s\n", part->name);
488a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        printf("\t\tflags = %s\n",
489a6391f1006b961ca89d1c79a826375380684a4deSan Mehat               part->flags & PART_ACTIVE_FLAG ? "Active" : "None");
490a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        printf("\t\ttype = %s\n",
491a6391f1006b961ca89d1c79a826375380684a4deSan Mehat               part->type == PC_PART_TYPE_LINUX ? "Linux" : "Unknown");
492a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (part->len_kb == (uint32_t)-1)
493a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            printf("\t\tlen = rest of disk\n");
494a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        else
495a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            printf("\t\tlen = %uKB\n", part->len_kb);
496a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
497a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("Total number of partitions: %d\n", cnt);
498a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    printf("\n");
499a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
500a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 0;
501a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
502a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
503a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstruct part_info *
504a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfind_part(struct disk_info *dinfo, const char *name)
505a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
506a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    struct part_info *pinfo;
507a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int cnt;
508a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
509a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    for (cnt = 0; cnt < dinfo->num_parts; ++cnt) {
510a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        pinfo = &dinfo->part_lst[cnt];
511a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!strcmp(pinfo->name, name))
512a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return pinfo;
513a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
514a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
515a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return NULL;
516a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
517a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
518a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* NOTE: If the returned ptr is non-NULL, it must be freed by the caller. */
519a6391f1006b961ca89d1c79a826375380684a4deSan Mehatchar *
520a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfind_part_device(struct disk_info *dinfo, const char *name)
521a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
522a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    switch (dinfo->scheme) {
523a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case PART_SCHEME_MBR:
524a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            return find_mbr_part(dinfo, name);
525a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        case PART_SCHEME_GPT:
52601dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("GPT is presently not supported");
527a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
528a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        default:
52901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Unknown partition table scheme");
530a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
531a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
532a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
533a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return NULL;
534a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
535a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
536a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
537