source: mainline/uspace/lib/label/src/gpt.c@ 3faa03d

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

Liblabel reading GPT and MBR partitions (primary only).

  • Property mode set to 100644
File size: 5.7 KB
Line 
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>
39#include <stdlib.h>
40
41#include "std/gpt.h"
42#include "gpt.h"
43
44static int gpt_open(service_id_t, label_t **);
45static int gpt_create(service_id_t, label_t **);
46static void gpt_close(label_t *);
47static int gpt_destroy(label_t *);
48static label_part_t *gpt_part_first(label_t *);
49static label_part_t *gpt_part_next(label_part_t *);
50static void gpt_part_get_info(label_part_t *, label_part_info_t *);
51static int gpt_part_create(label_t *, label_part_spec_t *, label_part_t **);
52static int gpt_part_destroy(label_part_t *);
53
54static int gpt_pte_to_part(label_t *, gpt_entry_t *);
55
56const uint8_t efi_signature[8] = {
57 /* "EFI PART" in ASCII */
58 0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54
59};
60
61label_ops_t gpt_label_ops = {
62 .open = gpt_open,
63 .create = gpt_create,
64 .close = gpt_close,
65 .destroy = gpt_destroy,
66 .part_first = gpt_part_first,
67 .part_next = gpt_part_next,
68 .part_get_info = gpt_part_get_info,
69 .part_create = gpt_part_create,
70 .part_destroy = gpt_part_destroy
71};
72
73static int gpt_open(service_id_t sid, label_t **rlabel)
74{
75 label_t *label = NULL;
76 gpt_header_t *gpt_hdr = NULL;
77 gpt_entry_t *eptr;
78 uint8_t *etable = NULL;
79 size_t bsize;
80 uint32_t num_entries;
81 uint32_t esize;
82 uint32_t bcnt;
83 uint64_t ba;
84 uint32_t entry;
85 int i;
86 int rc;
87
88 rc = block_get_bsize(sid, &bsize);
89 if (rc != EOK) {
90 rc = EIO;
91 goto error;
92 }
93
94 if (bsize < 512 || (bsize % 512) != 0) {
95 rc = EINVAL;
96 goto error;
97 }
98
99 gpt_hdr = calloc(1, bsize);
100 if (gpt_hdr == NULL) {
101 rc = ENOMEM;
102 goto error;
103 }
104
105 rc = block_read_direct(sid, GPT_HDR_BA, 1, gpt_hdr);
106 if (rc != EOK) {
107 rc = EIO;
108 goto error;
109 }
110
111 label = calloc(1, sizeof(label_t));
112 if (label == NULL)
113 return ENOMEM;
114
115 list_initialize(&label->parts);
116
117 for (i = 0; i < 8; ++i) {
118 if (gpt_hdr->efi_signature[i] != efi_signature[i]) {
119 rc = EINVAL;
120 goto error;
121 }
122 }
123
124 num_entries = uint32_t_le2host(gpt_hdr->num_entries);
125 esize = uint32_t_le2host(gpt_hdr->entry_size);
126 bcnt = (num_entries + esize - 1) / esize;
127 ba = uint64_t_le2host(gpt_hdr->entry_lba);
128
129 if (num_entries < 1) {
130 rc = EINVAL;
131 goto error;
132 }
133
134 if (esize < sizeof(gpt_entry_t)) {
135 rc = EINVAL;
136 goto error;
137 }
138
139 etable = calloc(num_entries, esize);
140 if (etable == NULL) {
141 rc = ENOMEM;
142 goto error;
143 }
144
145 rc = block_read_direct(sid, ba, bcnt, etable);
146 if (rc != EOK) {
147 rc = EIO;
148 goto error;
149 }
150
151 for (entry = 0; entry < num_entries; entry++) {
152 eptr = (gpt_entry_t *)(etable + entry * esize);
153 rc = gpt_pte_to_part(label, eptr);
154 if (rc != EOK)
155 goto error;
156 }
157
158 free(etable);
159 etable = NULL;
160 free(gpt_hdr);
161 gpt_hdr = NULL;
162
163 label->ops = &gpt_label_ops;
164 label->ltype = lt_gpt;
165 *rlabel = label;
166 return EOK;
167error:
168 free(etable);
169 free(gpt_hdr);
170 free(label);
171 return rc;
172}
173
174static int gpt_create(service_id_t sid, label_t **rlabel)
175{
176 return EOK;
177}
178
179static void gpt_close(label_t *label)
180{
181 free(label);
182}
183
184static int gpt_destroy(label_t *label)
185{
186 return EOK;
187}
188
189static label_part_t *gpt_part_first(label_t *label)
190{
191 link_t *link;
192
193 link = list_first(&label->parts);
194 if (link == NULL)
195 return NULL;
196
197 return list_get_instance(link, label_part_t, llabel);
198}
199
200static label_part_t *gpt_part_next(label_part_t *part)
201{
202 link_t *link;
203
204 link = list_next(&part->llabel, &part->label->parts);
205 if (link == NULL)
206 return NULL;
207
208 return list_get_instance(link, label_part_t, llabel);
209}
210
211static void gpt_part_get_info(label_part_t *part, label_part_info_t *pinfo)
212{
213 pinfo->block0 = part->block0;
214 pinfo->nblocks = part->nblocks;
215}
216
217static int gpt_part_create(label_t *label, label_part_spec_t *pspec,
218 label_part_t **rpart)
219{
220 return EOK;
221}
222
223static int gpt_part_destroy(label_part_t *part)
224{
225 return EOK;
226}
227
228static int gpt_pte_to_part(label_t *label, gpt_entry_t *pte)
229{
230 label_part_t *part;
231 bool present;
232 uint64_t b0, b1;
233 int i;
234
235 present = false;
236 for (i = 0; i < 8; i++)
237 if (pte->part_type[i] != 0x00)
238 present = true;
239
240 if (!present)
241 return EOK;
242
243 part = calloc(1, sizeof(label_part_t));
244 if (part == NULL)
245 return ENOMEM;
246
247 b0 = uint64_t_le2host(pte->start_lba);
248 b1 = uint64_t_le2host(pte->end_lba);
249 if (b1 <= b0)
250 return EINVAL;
251
252 part->block0 = b0;
253 part->nblocks = b1 - b0 + 1;
254
255 part->label = label;
256 list_append(&part->llabel, &label->parts);
257 return EOK;
258}
259
260/** @}
261 */
Note: See TracBrowser for help on using the repository browser.