source: mainline/uspace/lib/label/src/gpt.c@ 6bc542b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6bc542b was 6bc542b, checked in by Jiri Svoboda <jiri@…>, 10 years ago

Allocate and create partition with libfdisk (except actual modification of on-disk label).

  • Property mode set to 100644
File size: 6.7 KB
RevLine 
[3faa03d]1/*
2 * Copyright (c) 2015 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup liblabel
30 * @{
31 */
32/**
33 * @file GUID Partition Table label.
34 */
35
36#include <block.h>
37#include <byteorder.h>
38#include <errno.h>
[1626cd4]39#include <mem.h>
[3faa03d]40#include <stdlib.h>
41
42#include "std/gpt.h"
43#include "gpt.h"
44
45static int gpt_open(service_id_t, label_t **);
46static int gpt_create(service_id_t, label_t **);
47static void gpt_close(label_t *);
48static int gpt_destroy(label_t *);
[1626cd4]49static int gpt_get_info(label_t *, label_info_t *);
[3faa03d]50static label_part_t *gpt_part_first(label_t *);
51static label_part_t *gpt_part_next(label_part_t *);
52static void gpt_part_get_info(label_part_t *, label_part_info_t *);
53static int gpt_part_create(label_t *, label_part_spec_t *, label_part_t **);
54static int gpt_part_destroy(label_part_t *);
55
[1626cd4]56static int gpt_pte_to_part(label_t *, gpt_entry_t *, int);
[3faa03d]57
58const uint8_t efi_signature[8] = {
59 /* "EFI PART" in ASCII */
60 0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54
61};
62
63label_ops_t gpt_label_ops = {
64 .open = gpt_open,
65 .create = gpt_create,
66 .close = gpt_close,
67 .destroy = gpt_destroy,
[1626cd4]68 .get_info = gpt_get_info,
[3faa03d]69 .part_first = gpt_part_first,
70 .part_next = gpt_part_next,
71 .part_get_info = gpt_part_get_info,
72 .part_create = gpt_part_create,
73 .part_destroy = gpt_part_destroy
74};
75
76static int gpt_open(service_id_t sid, label_t **rlabel)
77{
78 label_t *label = NULL;
79 gpt_header_t *gpt_hdr = NULL;
80 gpt_entry_t *eptr;
81 uint8_t *etable = NULL;
82 size_t bsize;
83 uint32_t num_entries;
84 uint32_t esize;
85 uint32_t bcnt;
86 uint64_t ba;
87 uint32_t entry;
[1626cd4]88 uint64_t ba_min, ba_max;
[3faa03d]89 int i;
90 int rc;
91
92 rc = block_get_bsize(sid, &bsize);
93 if (rc != EOK) {
94 rc = EIO;
95 goto error;
96 }
97
98 if (bsize < 512 || (bsize % 512) != 0) {
99 rc = EINVAL;
100 goto error;
101 }
102
103 gpt_hdr = calloc(1, bsize);
104 if (gpt_hdr == NULL) {
105 rc = ENOMEM;
106 goto error;
107 }
108
109 rc = block_read_direct(sid, GPT_HDR_BA, 1, gpt_hdr);
110 if (rc != EOK) {
111 rc = EIO;
112 goto error;
113 }
114
115 label = calloc(1, sizeof(label_t));
116 if (label == NULL)
117 return ENOMEM;
118
119 list_initialize(&label->parts);
120
121 for (i = 0; i < 8; ++i) {
122 if (gpt_hdr->efi_signature[i] != efi_signature[i]) {
123 rc = EINVAL;
124 goto error;
125 }
126 }
127
128 num_entries = uint32_t_le2host(gpt_hdr->num_entries);
129 esize = uint32_t_le2host(gpt_hdr->entry_size);
130 bcnt = (num_entries + esize - 1) / esize;
131 ba = uint64_t_le2host(gpt_hdr->entry_lba);
[1626cd4]132 ba_min = uint64_t_le2host(gpt_hdr->first_usable_lba);
133 ba_max = uint64_t_le2host(gpt_hdr->last_usable_lba);
[3faa03d]134
135 if (num_entries < 1) {
136 rc = EINVAL;
137 goto error;
138 }
139
140 if (esize < sizeof(gpt_entry_t)) {
141 rc = EINVAL;
142 goto error;
143 }
144
[1626cd4]145 if (ba_max < ba_min) {
146 rc = EINVAL;
147 goto error;
148 }
149
[3faa03d]150 etable = calloc(num_entries, esize);
151 if (etable == NULL) {
152 rc = ENOMEM;
153 goto error;
154 }
155
156 rc = block_read_direct(sid, ba, bcnt, etable);
157 if (rc != EOK) {
158 rc = EIO;
159 goto error;
160 }
161
162 for (entry = 0; entry < num_entries; entry++) {
163 eptr = (gpt_entry_t *)(etable + entry * esize);
[1626cd4]164 rc = gpt_pte_to_part(label, eptr, entry + 1);
[3faa03d]165 if (rc != EOK)
166 goto error;
167 }
168
169 free(etable);
170 etable = NULL;
171 free(gpt_hdr);
172 gpt_hdr = NULL;
173
174 label->ops = &gpt_label_ops;
175 label->ltype = lt_gpt;
[1626cd4]176 label->ablock0 = ba_min;
177 label->anblocks = ba_max - ba_min + 1;
[3faa03d]178 *rlabel = label;
179 return EOK;
180error:
181 free(etable);
182 free(gpt_hdr);
183 free(label);
184 return rc;
185}
186
187static int gpt_create(service_id_t sid, label_t **rlabel)
188{
189 return EOK;
190}
191
192static void gpt_close(label_t *label)
193{
194 free(label);
195}
196
197static int gpt_destroy(label_t *label)
198{
199 return EOK;
200}
201
[1626cd4]202static int gpt_get_info(label_t *label, label_info_t *linfo)
203{
204 memset(linfo, 0, sizeof(label_info_t));
205 linfo->dcnt = dc_label;
206 linfo->ltype = lt_gpt;
207 linfo->ablock0 = label->ablock0;
208 linfo->anblocks = label->anblocks;
209 return EOK;
210}
211
[3faa03d]212static label_part_t *gpt_part_first(label_t *label)
213{
214 link_t *link;
215
216 link = list_first(&label->parts);
217 if (link == NULL)
218 return NULL;
219
220 return list_get_instance(link, label_part_t, llabel);
221}
222
223static label_part_t *gpt_part_next(label_part_t *part)
224{
225 link_t *link;
226
227 link = list_next(&part->llabel, &part->label->parts);
228 if (link == NULL)
229 return NULL;
230
231 return list_get_instance(link, label_part_t, llabel);
232}
233
234static void gpt_part_get_info(label_part_t *part, label_part_info_t *pinfo)
235{
[1626cd4]236 pinfo->index = part->index;
[3faa03d]237 pinfo->block0 = part->block0;
238 pinfo->nblocks = part->nblocks;
239}
240
241static int gpt_part_create(label_t *label, label_part_spec_t *pspec,
242 label_part_t **rpart)
243{
[6bc542b]244 label_part_t *part;
245
246 part = calloc(1, sizeof(label_part_t));
247 if (part == NULL)
248 return ENOMEM;
249
250 /* XXX Verify index, block0, nblocks */
251
252 part->index = pspec->index;
253 part->block0 = pspec->block0;
254 part->nblocks = pspec->nblocks;
255
256 /* XXX Modify partition table */
257
258 part->label = label;
259 list_append(&part->llabel, &label->parts);
260
261 *rpart = part;
262 return EOK;
[3faa03d]263}
264
265static int gpt_part_destroy(label_part_t *part)
266{
[1626cd4]267 return ENOTSUP;
[3faa03d]268}
269
[1626cd4]270static int gpt_pte_to_part(label_t *label, gpt_entry_t *pte, int index)
[3faa03d]271{
272 label_part_t *part;
273 bool present;
274 uint64_t b0, b1;
275 int i;
276
277 present = false;
278 for (i = 0; i < 8; i++)
279 if (pte->part_type[i] != 0x00)
280 present = true;
281
282 if (!present)
283 return EOK;
284
285 part = calloc(1, sizeof(label_part_t));
286 if (part == NULL)
287 return ENOMEM;
288
289 b0 = uint64_t_le2host(pte->start_lba);
290 b1 = uint64_t_le2host(pte->end_lba);
291 if (b1 <= b0)
292 return EINVAL;
293
[1626cd4]294 part->index = index;
[3faa03d]295 part->block0 = b0;
296 part->nblocks = b1 - b0 + 1;
297
298 part->label = label;
299 list_append(&part->llabel, &label->parts);
300 return EOK;
301}
302
303/** @}
304 */
Note: See TracBrowser for help on using the repository browser.