source: rtems/cpukit/libblock/src/bdpart-read.c @ 6780829

4.104.115
Last change on this file since 6780829 was 6780829, checked in by Sebastian Huber <sebastian.huber@…>, on 04/30/10 at 08:42:13

2010-04-30 Sebastian Huber <sebastian.huber@…>

  • libblock/src/bdpart.c: Removed file.
  • libblock/src/bdpart-create.c, libblock/src/bdpart-dump.c, libblock/src/bdpart-mount.c, libblock/src/bdpart-read.c, libblock/src/bdpart-register.c, libblock/src/bdpart-sort.c, libblock/src/bdpart-write.c: New files.
  • libblock/include/rtems/bdpart.h: Moved some definitions from bdpart.c.
  • libblock/Makefile.am: Update for file changes.
  • Property mode set to 100644
File size: 7.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bdpart
5 *
6 * Block device partition management.
7 */
8
9/*
10 * Copyright (c) 2009, 2010
11 * embedded brains GmbH
12 * Obere Lagerstr. 30
13 * D-82178 Puchheim
14 * Germany
15 * <rtems@embedded-brains.de>
16 *
17 * The license and distribution terms for this file may be
18 * found in the file LICENSE in this distribution or at
19 * http://www.rtems.com/license/LICENSE.
20 */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#include <rtems.h>
27#include <rtems/bdbuf.h>
28#include <rtems/bdpart.h>
29#include <rtems/endian.h>
30
31#define RTEMS_BDPART_MBR_PARTITION_TYPE( type) \
32  { \
33    (type), 0xa2U, 0x2eU, 0x38U, \
34    0x38U, 0xb5U, 0xdeU, 0x11U, \
35    0xbcU, 0x13U, 0x00U, 0x1dU, \
36    0x09U, 0xb0U, 0x5fU, 0xa4U \
37  }
38
39static const uuid_t RTEMS_BDPART_MBR_MASTER_TYPE =
40  RTEMS_BDPART_MBR_PARTITION_TYPE( RTEMS_BDPART_MBR_EMPTY);
41
42void rtems_bdpart_to_partition_type( uint8_t mbr_type, uuid_t type)
43{
44  type [0] = mbr_type;
45  memcpy( type + 1, RTEMS_BDPART_MBR_MASTER_TYPE + 1, sizeof( uuid_t) - 1);
46}
47
48bool rtems_bdpart_to_mbr_partition_type(
49  const uuid_t type,
50  uint8_t *mbr_type
51)
52{
53  *mbr_type = rtems_bdpart_mbr_partition_type( type);
54
55  return memcmp(
56    type + 1,
57    RTEMS_BDPART_MBR_MASTER_TYPE + 1,
58    sizeof( uuid_t) - 1
59  ) == 0;
60}
61
62/*
63 * FIXME: This code should the deviceio interface and not the bdbug interface.
64 */
65rtems_status_code rtems_bdpart_get_disk_data(
66  const char *disk_name,
67  dev_t *disk,
68  rtems_blkdev_bnum *disk_end
69)
70{
71  rtems_status_code sc = RTEMS_SUCCESSFUL;
72  int rv = 0;
73  rtems_blkdev_bnum disk_begin = 0;
74  rtems_blkdev_bnum block_size = 0;
75  rtems_disk_device *dd = NULL;
76  struct stat st;
77
78  /* Get disk handle */
79  rv = stat( disk_name, &st);
80  if (rv != 0) {
81    return RTEMS_INVALID_NAME;
82  }
83  *disk = st.st_rdev;
84
85  /* Get disk begin, end and block size */
86  dd = rtems_disk_obtain( *disk);
87  if (dd == NULL) {
88    return RTEMS_INVALID_NAME;
89  }
90  disk_begin = dd->start;
91  *disk_end = dd->size;
92  block_size = dd->block_size;
93  sc = rtems_disk_release( dd);
94  if (sc != RTEMS_SUCCESSFUL) {
95    return sc;
96  }
97
98  /* Check block size */
99  if (block_size < RTEMS_BDPART_BLOCK_SIZE) {
100    return RTEMS_IO_ERROR;
101  }
102
103  /* Check that we have do not have a logical disk */
104  if (disk_begin != 0) {
105    return RTEMS_IO_ERROR;
106  }
107
108  return RTEMS_SUCCESSFUL;
109}
110
111static bool rtems_bdpart_is_valid_record( const uint8_t *data)
112{
113  return data [RTEMS_BDPART_MBR_OFFSET_SIGNATURE_0]
114      == RTEMS_BDPART_MBR_SIGNATURE_0
115    && data [RTEMS_BDPART_MBR_OFFSET_SIGNATURE_1]
116      == RTEMS_BDPART_MBR_SIGNATURE_1;
117}
118
119static rtems_blkdev_bnum rtems_bdpart_next_ebr( const uint8_t *data)
120{
121  rtems_blkdev_bnum begin =
122    rtems_uint32_from_little_endian( data + RTEMS_BDPART_MBR_OFFSET_BEGIN);
123  uint8_t type = data [RTEMS_BDPART_MBR_OFFSET_TYPE];
124
125  if (type == RTEMS_BDPART_MBR_EXTENDED) {
126    return begin;
127  } else {
128    return 0;
129  }
130}
131
132static rtems_status_code rtems_bdpart_read_mbr_partition(
133  const uint8_t *data,
134  rtems_bdpart_partition **p,
135  const rtems_bdpart_partition *p_end,
136  rtems_blkdev_bnum *ep_begin
137)
138{
139  rtems_blkdev_bnum begin =
140    rtems_uint32_from_little_endian( data + RTEMS_BDPART_MBR_OFFSET_BEGIN);
141  rtems_blkdev_bnum size =
142    rtems_uint32_from_little_endian( data + RTEMS_BDPART_MBR_OFFSET_SIZE);
143  rtems_blkdev_bnum end = begin + size;
144  uint8_t type = data [RTEMS_BDPART_MBR_OFFSET_TYPE];
145
146  if (type == RTEMS_BDPART_MBR_EMPTY) {
147    return RTEMS_SUCCESSFUL;
148  } else if (*p == p_end) {
149    return RTEMS_TOO_MANY;
150  } else if (begin >= end) {
151    return RTEMS_IO_ERROR;
152  } else if (type == RTEMS_BDPART_MBR_EXTENDED) {
153    if (ep_begin != NULL) {
154      *ep_begin = begin;
155    }
156  } else {
157    /* Increment partition index */
158    ++(*p);
159
160    /* Clear partition */
161    memset( *p, 0, sizeof( rtems_bdpart_partition));
162
163    /* Set values */
164    (*p)->begin = begin;
165    (*p)->end = end;
166    rtems_bdpart_to_partition_type( type, (*p)->type);
167    (*p)->flags = data [RTEMS_BDPART_MBR_OFFSET_FLAGS];
168  }
169
170  return RTEMS_SUCCESSFUL;
171}
172
173static rtems_status_code rtems_bdpart_read_record(
174  dev_t disk,
175  rtems_blkdev_bnum index,
176  rtems_bdbuf_buffer **block
177)
178{
179  rtems_status_code sc = RTEMS_SUCCESSFUL;
180
181  /* Release previous block if necessary */
182  if (*block != NULL) {
183    sc = rtems_bdbuf_release( *block);
184    if (sc != RTEMS_SUCCESSFUL) {
185      return sc;
186    }
187  }
188
189  /* Read the record block */
190  sc = rtems_bdbuf_read( disk, index, block);
191  if (sc != RTEMS_SUCCESSFUL) {
192    return sc;
193  }
194
195  /* just in case block did not get filled in */
196  if ( *block == NULL ) {
197    return RTEMS_INVALID_ADDRESS;
198  }
199
200  /* Check MBR signature */
201  if (!rtems_bdpart_is_valid_record( (*block)->buffer)) {
202    return RTEMS_IO_ERROR;
203  }
204
205  return RTEMS_SUCCESSFUL;
206}
207
208rtems_status_code rtems_bdpart_read(
209  const char *disk_name,
210  rtems_bdpart_format *format,
211  rtems_bdpart_partition *pt,
212  size_t *count
213)
214{
215  rtems_status_code sc = RTEMS_SUCCESSFUL;
216  rtems_status_code esc = RTEMS_SUCCESSFUL;
217  rtems_bdbuf_buffer *block = NULL;
218  rtems_bdpart_partition *p = pt - 1;
219  const rtems_bdpart_partition *p_end = pt + (count != NULL ? *count : 0);
220  rtems_blkdev_bnum ep_begin = 0; /* Extended partition begin */
221  rtems_blkdev_bnum ebr = 0; /* Extended boot record block index */
222  rtems_blkdev_bnum disk_end = 0;
223  dev_t disk = 0;
224  size_t i = 0;
225  const uint8_t *data = NULL;
226
227  /* Check parameter */
228  if (format == NULL || pt == NULL || count == NULL) {
229    return RTEMS_INVALID_ADDRESS;
230  }
231
232  /* Set count to a save value */
233  *count = 0;
234
235  /* Get disk data */
236  sc = rtems_bdpart_get_disk_data( disk_name, &disk, &disk_end);
237  if (sc != RTEMS_SUCCESSFUL) {
238    return sc;
239  }
240
241  /* Read MBR */
242  sc = rtems_bdpart_read_record( disk, 0, &block);
243  if (sc != RTEMS_SUCCESSFUL) {
244    esc = sc;
245    goto cleanup;
246  }
247
248  /* Read the first partition entry */
249  data = block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_0;
250  sc = rtems_bdpart_read_mbr_partition( data, &p, p_end, &ep_begin);
251  if (sc != RTEMS_SUCCESSFUL) {
252    esc = sc;
253    goto cleanup;
254  }
255
256  /* Determine if we have a MBR or GPT format */
257  if (rtems_bdpart_mbr_partition_type( p->type) == RTEMS_BDPART_MBR_GPT) {
258    esc = RTEMS_NOT_IMPLEMENTED;
259    goto cleanup;
260  }
261
262  /* Set format */
263  format->type = RTEMS_BDPART_FORMAT_MBR;
264  format->mbr.disk_id = rtems_uint32_from_little_endian(
265    block->buffer + RTEMS_BDPART_MBR_OFFSET_DISK_ID
266  );
267  format->mbr.dos_compatibility = true;
268
269  /* Iterate through the rest of the primary partition table */
270  for (i = 1; i < 4; ++i) {
271    data += RTEMS_BDPART_MBR_TABLE_ENTRY_SIZE;
272
273    sc = rtems_bdpart_read_mbr_partition( data, &p, p_end, &ep_begin);
274    if (sc != RTEMS_SUCCESSFUL) {
275      esc = sc;
276      goto cleanup;
277    }
278  }
279
280  /* Iterate through the logical partitions within the extended partition */
281  ebr = ep_begin;
282  while (ebr != 0) {
283    rtems_blkdev_bnum tmp = 0;
284
285    /* Read EBR */
286    sc = rtems_bdpart_read_record( disk, ebr, &block);
287    if (sc != RTEMS_SUCCESSFUL) {
288      esc = sc;
289      goto cleanup;
290    }
291
292    /* Read first partition entry */
293    sc = rtems_bdpart_read_mbr_partition(
294      block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_0,
295      &p,
296      p_end,
297      NULL
298    );
299    if (sc != RTEMS_SUCCESSFUL) {
300      esc = sc;
301      goto cleanup;
302    }
303
304    /* Adjust partition begin */
305    tmp = p->begin + ebr;
306    if (tmp > p->begin) {
307      p->begin = tmp;
308    } else {
309      esc = RTEMS_IO_ERROR;
310      goto cleanup;
311    }
312
313    /* Adjust partition end */
314    tmp = p->end + ebr;
315    if (tmp > p->end) {
316      p->end = tmp;
317    } else {
318      esc = RTEMS_IO_ERROR;
319      goto cleanup;
320    }
321
322    /* Read second partition entry for next EBR block */
323    ebr = rtems_bdpart_next_ebr(
324      block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_1
325    );
326    if (ebr != 0) {
327      /* Adjust partition EBR block index */
328      tmp = ebr + ep_begin;
329      if (tmp > ebr) {
330        ebr = tmp;
331      } else {
332        esc = RTEMS_IO_ERROR;
333        goto cleanup;
334      }
335    }
336  }
337
338  /* Return partition count */
339  *count = (size_t) (p - pt + 1);
340
341cleanup:
342
343  if (block != NULL) {
344    rtems_bdbuf_release( block);
345  }
346
347  return esc;
348}
Note: See TracBrowser for help on using the repository browser.