source: mainline/uspace/lib/label/src/mbr.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: 5.9 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 Master Boot Record label
34 */
35
36#include <block.h>
37#include <byteorder.h>
38#include <errno.h>
39#include <mem.h>
40#include <stdlib.h>
41
42#include "std/mbr.h"
43#include "mbr.h"
44
45static int mbr_open(service_id_t, label_t **);
46static int mbr_create(service_id_t, label_t **);
47static void mbr_close(label_t *);
48static int mbr_destroy(label_t *);
49static int mbr_get_info(label_t *, label_info_t *);
50static label_part_t *mbr_part_first(label_t *);
51static label_part_t *mbr_part_next(label_part_t *);
52static void mbr_part_get_info(label_part_t *, label_part_info_t *);
53static int mbr_part_create(label_t *, label_part_spec_t *, label_part_t **);
54static int mbr_part_destroy(label_part_t *);
55
56static int mbr_pte_to_part(label_t *, mbr_pte_t *, int);
57
58label_ops_t mbr_label_ops = {
59 .open = mbr_open,
60 .create = mbr_create,
61 .close = mbr_close,
62 .destroy = mbr_destroy,
63 .get_info = mbr_get_info,
64 .part_first = mbr_part_first,
65 .part_next = mbr_part_next,
66 .part_get_info = mbr_part_get_info,
67 .part_create = mbr_part_create,
68 .part_destroy = mbr_part_destroy
69};
70
71static int mbr_open(service_id_t sid, label_t **rlabel)
72{
73 label_t *label = NULL;
74 mbr_br_block_t *mbr = NULL;
75 mbr_pte_t *eptr;
76 uint16_t sgn;
77 size_t bsize;
78 aoff64_t nblocks;
79 uint32_t entry;
80 int rc;
81
82 rc = block_get_bsize(sid, &bsize);
83 if (rc != EOK) {
84 rc = EIO;
85 goto error;
86 }
87
88 rc = block_get_nblocks(sid, &nblocks);
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 if (nblocks < mbr_ablock0) {
100 rc = EINVAL;
101 goto error;
102 }
103
104 mbr = calloc(1, bsize);
105 if (mbr == NULL) {
106 rc = ENOMEM;
107 goto error;
108 }
109
110 rc = block_read_direct(sid, mbr_ba, 1, mbr);
111 if (rc != EOK) {
112 rc = EIO;
113 goto error;
114 }
115
116 label = calloc(1, sizeof(label_t));
117 if (label == NULL)
118 return ENOMEM;
119
120 list_initialize(&label->parts);
121
122 /* Verify boot record signature */
123 sgn = uint16_t_le2host(mbr->signature);
124 if (sgn != mbr_br_signature) {
125 rc = EIO;
126 goto error;
127 }
128
129 for (entry = 0; entry < mbr_nprimary; entry++) {
130 eptr = &mbr->pte[entry];
131 rc = mbr_pte_to_part(label, eptr, entry + 1);
132 if (rc != EOK)
133 goto error;
134 }
135
136 free(mbr);
137 mbr = NULL;
138
139 label->ops = &mbr_label_ops;
140 label->ltype = lt_mbr;
141 label->ablock0 = mbr_ablock0;
142 label->anblocks = nblocks - mbr_ablock0;
143 *rlabel = label;
144 return EOK;
145error:
146 free(mbr);
147 free(label);
148 return rc;
149}
150
151static int mbr_create(service_id_t sid, label_t **rlabel)
152{
153 return EOK;
154}
155
156static void mbr_close(label_t *label)
157{
158 free(label);
159}
160
161static int mbr_destroy(label_t *label)
162{
163 return EOK;
164}
165
166static int mbr_get_info(label_t *label, label_info_t *linfo)
167{
168 memset(linfo, 0, sizeof(label_info_t));
169 linfo->dcnt = dc_label;
170 linfo->ltype = lt_mbr;
171 linfo->ablock0 = label->ablock0;
172 linfo->anblocks = label->anblocks;
173 return EOK;
174}
175
176static label_part_t *mbr_part_first(label_t *label)
177{
178 link_t *link;
179
180 link = list_first(&label->parts);
181 if (link == NULL)
182 return NULL;
183
184 return list_get_instance(link, label_part_t, llabel);
185}
186
187static label_part_t *mbr_part_next(label_part_t *part)
188{
189 link_t *link;
190
191 link = list_next(&part->llabel, &part->label->parts);
192 if (link == NULL)
193 return NULL;
194
195 return list_get_instance(link, label_part_t, llabel);
196}
197
198static void mbr_part_get_info(label_part_t *part, label_part_info_t *pinfo)
199{
200 pinfo->index = part->index;
201 pinfo->block0 = part->block0;
202 pinfo->nblocks = part->nblocks;
203}
204
205static int mbr_part_create(label_t *label, label_part_spec_t *pspec,
206 label_part_t **rpart)
207{
208 label_part_t *part;
209
210 part = calloc(1, sizeof(label_part_t));
211 if (part == NULL)
212 return ENOMEM;
213
214 part->index = pspec->index;
215 part->block0 = pspec->block0;
216 part->nblocks = pspec->nblocks;
217
218 part->label = label;
219
220 *rpart = part;
221 return EOK;
222}
223
224static int mbr_part_destroy(label_part_t *part)
225{
226 return ENOTSUP;
227}
228
229static int mbr_pte_to_part(label_t *label, mbr_pte_t *pte, int index)
230{
231 label_part_t *part;
232 uint32_t block0;
233 uint32_t nblocks;
234
235 block0 = uint32_t_le2host(pte->first_lba);
236 nblocks = uint32_t_le2host(pte->length);
237
238 /* See UEFI specification 2.0 section 5.2.1 Legacy Master Boot Record */
239 if (pte->ptype == mbr_pt_unused || pte->ptype == mbr_pt_extended ||
240 nblocks == 0)
241 return EOK;
242
243 part = calloc(1, sizeof(label_part_t));
244 if (part == NULL)
245 return ENOMEM;
246
247 part->index = index;
248 part->block0 = block0;
249 part->nblocks = nblocks;
250
251 /*
252 * TODO: Verify
253 * - partition must reside on disk
254 * - partition must not overlap any other partition
255 */
256
257 part->label = label;
258 list_append(&part->llabel, &label->parts);
259 return EOK;
260}
261
262/** @}
263 */
Note: See TracBrowser for help on using the repository browser.