source: mainline/uspace/lib/label/src/mbr.c@ 6a0d4ce2

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

Propagate label and partition block ranges and other info up through the stack.

  • 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 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 return ENOTSUP;
209}
210
211static int mbr_part_destroy(label_part_t *part)
212{
213 return ENOTSUP;
214}
215
216static int mbr_pte_to_part(label_t *label, mbr_pte_t *pte, int index)
217{
218 label_part_t *part;
219 uint32_t block0;
220 uint32_t nblocks;
221
222 block0 = uint32_t_le2host(pte->first_lba);
223 nblocks = uint32_t_le2host(pte->length);
224
225 /* See UEFI specification 2.0 section 5.2.1 Legacy Master Boot Record */
226 if (pte->ptype == mbr_pt_unused || pte->ptype == mbr_pt_extended ||
227 nblocks == 0)
228 return EOK;
229
230 part = calloc(1, sizeof(label_part_t));
231 if (part == NULL)
232 return ENOMEM;
233
234 part->index = index;
235 part->block0 = block0;
236 part->nblocks = nblocks;
237
238 /*
239 * TODO: Verify
240 * - partition must reside on disk
241 * - partition must not overlap any other partition
242 */
243
244 part->label = label;
245 list_append(&part->llabel, &label->parts);
246 return EOK;
247}
248
249/** @}
250 */
Note: See TracBrowser for help on using the repository browser.