source: rtems/cpukit/libblock/src/ide_part_table.c @ b61ad65

4.104.115
Last change on this file since b61ad65 was b61ad65, checked in by Joel Sherrill <joel.sherrill@…>, on 01/19/10 at 23:47:41

2010-01-19 Joel Sherrill <joel.sherrill@…>

  • libblock/src/ide_part_table.c: Another error path without a free(sector).
  • Property mode set to 100644
File size: 14.2 KB
RevLine 
[ef142d7]1/*****************************************************************************
2 *
3 * ide_part_table.c
4 *
5 * The implementation of library supporting "MS-DOS-style" partition table
6 *
7 *
8 * Copyright (C) 2002 OKTET Ltd., St.-Petersburg, Russia
9 *
10 * Author: Konstantin Abramenko <Konstantin.Abramenko@oktet.ru>
11 *         Alexander Kukuta <Alexander.Kukuta@oktet.ru>
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
[5b38506]15 *  http://www.rtems.com/license/LICENSE.
[ef142d7]16 *
17 * $Id$
18 *
19 *****************************************************************************/
20
[006fa1ef]21#if HAVE_CONFIG_H
22#include "config.h"
23#endif
24
[dbe06865]25#include <string.h>
[ef142d7]26
[006fa1ef]27#include <rtems/ide_part_table.h>
28
[ef142d7]29/*
30 * get_sector --
31 *      gets sector from the disk
32 *
33 * PARAMETERS:
34 *      dev        - device number
35 *      sector_num - number of sector to read
36 *      sector     - returned pointer to pointer to allocated
37 *                   sector_data_t structure
38 *
39 * RETURNS:
40 *      RTEMS_SUCCESSFUL, if success;
41 *      RTEMS_NO_MEMORY, if canot allocate memory for sector data;
42 *      other error codes returned by rtems_bdbuf_read().
43 *
44 * NOTES:
45 *      get_sector() operates with device via bdbuf library,
46 *      and does not support devices with sector size other than 512 bytes
47 */
48static rtems_status_code
[3899a537]49get_sector(dev_t dev, uint32_t sector_num, rtems_sector_data_t **sector)
[ef142d7]50{
[3899a537]51    rtems_sector_data_t *s;
52    rtems_bdbuf_buffer  *buf;
53    rtems_status_code    rc;
[048dcd2b]54
[ef142d7]55    if (sector == NULL)
56    {
57        return RTEMS_INTERNAL_ERROR;
58    }
59
[3899a537]60    s = (rtems_sector_data_t *) malloc(sizeof(rtems_sector_data_t) + RTEMS_IDE_SECTOR_SIZE);
[ef142d7]61    if (s == NULL)
62    {
63        return RTEMS_NO_MEMORY;
64    }
[048dcd2b]65
[ef142d7]66    rc = rtems_bdbuf_read(dev, sector_num, &buf);
67    if (rc != RTEMS_SUCCESSFUL)
68    {
69        free(s);
70        return rc;
71    }
[048dcd2b]72
[ef142d7]73    memcpy(s->data, buf->buffer, RTEMS_IDE_SECTOR_SIZE);
74    s->sector_num = sector_num;
75
76    *sector = s;
[048dcd2b]77
[ef142d7]78    rtems_bdbuf_release(buf);
[048dcd2b]79
[ef142d7]80    return RTEMS_SUCCESSFUL;
81}
82
83
84/*
85 * msdos_signature_check --
86 *      checks if the partition table sector has msdos signature
87 *
88 * PARAMETERS:
89 *      sector - sector to check
90 *
91 * RETURNS:
[4f971343]92 *      true if sector has msdos signature, false otherwise
[ef142d7]93 */
[e03c37a]94static bool
[3899a537]95msdos_signature_check (rtems_sector_data_t *sector)
[ef142d7]96{
[c01d95b7]97    uint8_t *p = sector->data + RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_OFFSET;
[ef142d7]98
99    return ((p[0] == RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_DATA1) &&
100            (p[1] == RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_DATA2));
101}
102
103
104/*
105 * is_extended --
106 *      checks if the partition type is extended
107 *
108 * PARAMETERS:
109 *      type - type of partition to check
110 *
111 * RETURNS:
[4f971343]112 *      true if partition type is extended, false otherwise
[ef142d7]113 */
[e03c37a]114static bool
[8b96149]115is_extended(uint8_t type)
[ef142d7]116{
117    return ((type == EXTENDED_PARTITION) || (type == LINUX_EXTENDED));
118}
119
[dbe06865]120/*
121 * is_fat_partition --
122 *      checks if the partition type is defined for FAT
123 *
124 * PARAMETERS:
125 *      type - type of partition to check
126 *
127 * RETURNS:
[4f971343]128 *      true if partition type is extended, false otherwise
[dbe06865]129 */
[e03c37a]130static bool
[8b96149]131is_fat_partition(uint8_t type)
[dbe06865]132{
[c01d95b7]133  static const uint8_t fat_part_types[] = {
[dbe06865]134    DOS_FAT12_PARTITION,DOS_FAT16_PARTITION,
135    DOS_P32MB_PARTITION,
136    FAT32_PARTITION    ,FAT32_LBA_PARTITION,
137    FAT16_LBA_PARTITION
138  };
139
140  return (NULL != memchr(fat_part_types,type,sizeof(fat_part_types)));
141}
142
[ef142d7]143
144/*
145 * data_to_part_desc --
146 *      parses raw partition table sector data
147 *      to partition description structure
148 *
149 * PARAMETERS:
150 *      data          - raw partition table sector data
151 *      new_part_desc - pointer to returned partition description structure
152 *
153 * RETURNS:
154 *      RTEMS_SUCCESSFUL, if success;
155 *      RTEMS_NO_MEMOTY, if cannot allocate memory for part_desc_t strucure;
156 *      RTEMS_INTERNAL_ERROR, if other error occurs.
157 */
158static rtems_status_code
[3899a537]159data_to_part_desc(uint8_t *data, rtems_part_desc_t **new_part_desc)
[ef142d7]160{
[3899a537]161    rtems_part_desc_t *part_desc;
162    uint32_t           temp;
[ef142d7]163
164    if (new_part_desc == NULL)
165    {
166        return RTEMS_INTERNAL_ERROR;
167    }
[048dcd2b]168
[ef142d7]169    *new_part_desc = NULL;
170
[3899a537]171    if ((part_desc = calloc(1, sizeof(rtems_part_desc_t))) == NULL)
[ef142d7]172    {
173        return RTEMS_NO_MEMORY;
174    }
175
176    part_desc->bootable = *(data + RTEMS_IDE_PARTITION_BOOTABLE_OFFSET);
177    part_desc->sys_type = *(data + RTEMS_IDE_PARTITION_SYS_TYPE_OFFSET);
178
179    /* read the offset start position and partition size in sectors */
180
181    /* due to incorrect data alignment one have to align data first */
[c01d95b7]182    memcpy(&temp, data + RTEMS_IDE_PARTITION_START_OFFSET, sizeof(uint32_t));
[ef142d7]183    part_desc->start = LE_TO_CPU_U32(temp);
184
[c01d95b7]185    memcpy(&temp, data + RTEMS_IDE_PARTITION_SIZE_OFFSET, sizeof(uint32_t));
[ef142d7]186    part_desc->size = LE_TO_CPU_U32(temp);
187
[dbe06865]188    /*
[8b96149]189     * use partitions that are
[dbe06865]190     * - extended
191     * or
192     * - FAT type and non-zero
193     */
194    if (is_extended(part_desc->sys_type) ||
[b2ac8a9]195       ((is_fat_partition(part_desc->sys_type)) && (part_desc->size != 0))) {
[dbe06865]196      *new_part_desc = part_desc;
197    }
[8b96149]198    else {
[dbe06865]199      /* empty partition */
200      free(part_desc);
[ef142d7]201    }
202    return RTEMS_SUCCESSFUL;
203}
204
205
206/*
207 * read_extended_partition --
208 *      recursively reads extended partition sector from the device
209 *      and constructs the partition table tree
210 *
211 * PARAMETERS:
[8b96149]212 *      start    - start sector of primary extended partition, used for
[ef142d7]213 *                 calculation of absolute partition sector address
214 *      ext_part - description of extended partition to process
215 *
216 * RETURNS:
217 *      RTEMS_SUCCESSFUL if success,
218 *      RTEMS_NO_MEMOTY if cannot allocate memory for part_desc_t strucure,
219 *      RTEMS_INTERNAL_ERROR if other error occurs.
220 */
221static rtems_status_code
[3899a537]222read_extended_partition(uint32_t start, rtems_part_desc_t *ext_part)
[ef142d7]223{
[3899a537]224    int                  i;
225    dev_t                dev;
[b61ad65]226    rtems_sector_data_t *sector = NULL;
[3899a537]227    uint32_t             here;
228    uint8_t             *data;
229    rtems_part_desc_t   *new_part_desc;
230    rtems_status_code    rc;
[ef142d7]231
232    if ((ext_part == NULL) || (ext_part->disk_desc == NULL))
233    {
234        return RTEMS_INTERNAL_ERROR;
235    }
[048dcd2b]236
[ef142d7]237    dev = ext_part->disk_desc->dev;
238
239    /* get start sector of current extended partition */
240    here = ext_part->start;
241
242    /* get first extended partition sector */
243
244    rc = get_sector(dev, here, &sector);
245    if (rc != RTEMS_SUCCESSFUL)
246    {
[b61ad65]247        if (sector)
248            free(sector);
[ef142d7]249        return rc;
250    }
251
252    if (!msdos_signature_check(sector))
253    {
[b61ad65]254        free(sector);
[ef142d7]255        return RTEMS_INTERNAL_ERROR;
256    }
257
258    /* read and process up to 4 logical partition descriptors */
259
260    data = sector->data + RTEMS_IDE_PARTITION_TABLE_OFFSET;
261
[8b96149]262    for (i = 0; i < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER; i++)
[ef142d7]263    {
264        /* if data_to_part_desc fails skip this partition
265         * and parse the next one
266         */
267        rc = data_to_part_desc(data, &new_part_desc);
268        if (rc != RTEMS_SUCCESSFUL)
269        {
270            free(sector);
271            return rc;
272        }
[048dcd2b]273
[ef142d7]274        if (new_part_desc == NULL)
275        {
276            data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE;
277            continue;
278        }
279
280        ext_part->sub_part[i] = new_part_desc;
281        new_part_desc->ext_part = ext_part;
282        new_part_desc->disk_desc = ext_part->disk_desc;
283
[8b96149]284        if (is_extended(new_part_desc->sys_type))
[ef142d7]285        {
286            new_part_desc->log_id = EMPTY_PARTITION;
287            new_part_desc->start += start;
[8b96149]288            read_extended_partition(start, new_part_desc);
[ef142d7]289        }
[8b96149]290        else
[ef142d7]291        {
[3899a537]292            rtems_disk_desc_t *disk_desc = new_part_desc->disk_desc;
[ef142d7]293            disk_desc->partitions[disk_desc->last_log_id] = new_part_desc;
294            new_part_desc->log_id = ++disk_desc->last_log_id;
295            new_part_desc->start += here;
296            new_part_desc->end = new_part_desc->start + new_part_desc->size - 1;
297        }
298        data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE;
299    }
300
301    free(sector);
[048dcd2b]302
[ef142d7]303    return RTEMS_SUCCESSFUL;
304}
305
306
307/*
308 * read_mbr --
309 *      reads Master Boot Record (sector 0) of physical device and
310 *      constructs disk description structure
311 *
312 * PARAMETERS:
313 *      disk_desc - returned disc description structure
314 *
315 * RETURNS:
316 *      RTEMS_SUCCESSFUL if success,
317 *      RTEMS_INTERNAL_ERROR otherwise
318 */
319static rtems_status_code
[3899a537]320read_mbr(rtems_disk_desc_t *disk_desc)
[ef142d7]321{
[3899a537]322    int                  part_num;
[d3231fba]323    rtems_sector_data_t *sector = NULL;
[3899a537]324    rtems_part_desc_t   *part_desc;
325    uint8_t             *data;
326    rtems_status_code    rc;
327    dev_t                dev = disk_desc->dev;
[ef142d7]328
329    /* get MBR sector */
330    rc = get_sector(dev, 0, &sector);
331    if (rc != RTEMS_SUCCESSFUL)
332    {
[d3231fba]333        if (sector)
334            free(sector);
[ef142d7]335        return rc;
336    }
337
338    /* check if the partition table structure is MS-DOS style */
339    if (!msdos_signature_check(sector))
340    {
[b2ac8a9]341        free(sector);
[ef142d7]342        return RTEMS_INTERNAL_ERROR;
343    }
344
345    /* read and process 4 primary partition descriptors */
346
347    data = sector->data + RTEMS_IDE_PARTITION_TABLE_OFFSET;
348
349    for (part_num = 0;
350         part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
351         part_num++)
352    {
353        rc = data_to_part_desc(data, &part_desc);
354        if (rc != RTEMS_SUCCESSFUL)
355        {
356            free(sector);
357            return rc;
358        }
359
[8b96149]360        if (part_desc != NULL)
[ef142d7]361        {
362            part_desc->log_id = part_num + 1;
363            part_desc->disk_desc = disk_desc;
364            part_desc->end = part_desc->start + part_desc->size - 1;
365            disk_desc->partitions[part_num] = part_desc;
[8b96149]366        }
[ef142d7]367        else
368        {
369            disk_desc->partitions[part_num] = NULL;
370        }
371
372        data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE;
373    }
374
375    free(sector);
[048dcd2b]376
[ef142d7]377    disk_desc->last_log_id = RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
378
379    /* There cannot be more than one extended partition,
380       but we are to process each primary partition */
381    for (part_num = 0;
382         part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
383         part_num++)
384    {
[eb961961]385        part_desc = disk_desc->partitions[part_num];
386        if (part_desc != NULL && is_extended(part_desc->sys_type))
[ef142d7]387        {
[eb961961]388            read_extended_partition(part_desc->start, part_desc);
[ef142d7]389        }
390    }
391
392    return RTEMS_SUCCESSFUL;
393}
394
395
396/*
397 * partition free --
398 *      frees partition description structure
399 *
400 * PARAMETERS:
401 *      part_desc - returned disc description structure
402 *
403 * RETURNS:
404 *      N/A
405 */
406static void
[3899a537]407partition_free(rtems_part_desc_t *part_desc)
[ef142d7]408{
409    int part_num;
410
411    if (part_desc == NULL)
412        return;
[048dcd2b]413
[ef142d7]414    if (is_extended(part_desc->sys_type))
415    {
416        for (part_num = 0;
417             part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
418             part_num++)
419        {
420            partition_free(part_desc->sub_part[part_num]);
421        }
422    }
[048dcd2b]423
[ef142d7]424    free(part_desc);
425}
426
427
428/*
429 * rtems_ide_part_table_free - frees disk descriptor structure
430 *
431 * PARAMETERS:
432 *      disk_desc - disc descriptor structure to free
433 *
434 * RETURNS:
435 *      N/A
436 */
437void
[3899a537]438rtems_ide_part_table_free(rtems_disk_desc_t *disk_desc)
[ef142d7]439{
440    int part_num;
441
442    for (part_num = 0; part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER; part_num++)
443    {
444        partition_free(disk_desc->partitions[part_num]);
445    }
[048dcd2b]446
[ef142d7]447    free(disk_desc);
448}
449
450
451/*
452 * rtems_ide_part_table_get - reads partition table structure from the device
453 *                            and creates disk description structure
454 *
455 * PARAMETERS:
456 *      dev_name - path to physical device in /dev filesystem
457 *      disk_desc       - returned disc description structure
458 *
459 * RETURNS:
460 *      RTEMS_SUCCESSFUL if success,
461 *      RTEMS_INTERNAL_ERROR otherwise
462 */
463rtems_status_code
[3899a537]464rtems_ide_part_table_get(const char *dev_name, rtems_disk_desc_t *disk_desc)
[ef142d7]465{
466    struct stat         dev_stat;
467    rtems_status_code   rc;
468
469    rc = stat(dev_name, &dev_stat);
470    if (rc != RTEMS_SUCCESSFUL)
471    {
472        return RTEMS_INTERNAL_ERROR;
473    }
474
475    strncpy (disk_desc->dev_name, dev_name, 15);
[7baa484]476    disk_desc->dev = dev_stat.st_rdev;
[ef142d7]477    disk_desc->sector_size = (dev_stat.st_blksize) ? dev_stat.st_blksize :
478                                              RTEMS_IDE_SECTOR_SIZE;
479
480    rc = read_mbr(disk_desc);
481
482    return rc;
483}
484
485
486/*
487 * rtems_ide_part_table_initialize - initializes logical devices
488 *                                   on the physical IDE drive
489 *
490 * PARAMETERS:
491 *      dev_name - path to physical device in /dev filesystem
492 *
493 * RETURNS:
494 *      RTEMS_SUCCESSFUL if success,
495 *      RTEMS_NO_MEMOTY if cannot have not enough memory,
496 *      RTEMS_INTERNAL_ERROR if other error occurs.
497 */
498rtems_status_code
499rtems_ide_part_table_initialize(char *dev_name)
500{
501    int                         part_num;
502    dev_t                       dev;
[3899a537]503    rtems_disk_desc_t          *disk_desc;
[ef142d7]504    rtems_device_major_number   major;
505    rtems_device_minor_number   minor;
506    rtems_status_code           rc;
[3899a537]507    rtems_part_desc_t          *part_desc;
[ef142d7]508
509    /* logical device name /dev/hdxyy */
510    char                        name[RTEMS_IDE_PARTITION_DEV_NAME_LENGTH_MAX];
511
[3899a537]512    disk_desc = (rtems_disk_desc_t *) calloc(1, sizeof(rtems_disk_desc_t));
[ef142d7]513    if (disk_desc == NULL)
514    {
515        return RTEMS_NO_MEMORY;
516    }
[048dcd2b]517
[ef142d7]518    /* get partition table */
519    rc = rtems_ide_part_table_get(dev_name, disk_desc);
520    if (rc != RTEMS_SUCCESSFUL)
521    {
[47c2327]522        free(disk_desc);
[ef142d7]523        return rc;
524    }
525
526    /* To avoid device numbers conflicts we have to use for logic disk the same
527     * device major number as ATA device has, and minor number that equals to
528     * sum of logic disk partition number and the minor number of physical disk
529     */
530
531    rtems_filesystem_split_dev_t (disk_desc->dev, major, minor);
532
533    /* create logical disks on the physical one */
534    for (part_num = 0; part_num < disk_desc->last_log_id; part_num++)
535    {
536        sprintf(name, "%s%d", dev_name, part_num + 1);
537        dev = rtems_filesystem_make_dev_t(major, ++minor);
538
539        part_desc = disk_desc->partitions[part_num];
540        if (part_desc == NULL)
541        {
542            continue;
543        }
544
545        rc = rtems_disk_create_log(dev, disk_desc->dev, part_desc->start,
546                                   part_desc->size, name);
547        if (rc != RTEMS_SUCCESSFUL)
548        {
[d63a2c2]549            fprintf(stdout,"Cannot create device %s, error code %d\n", name, rc);
[ef142d7]550            continue;
551        }
552    }
553
554    rtems_ide_part_table_free(disk_desc);
555
556    return RTEMS_SUCCESSFUL;
557}
Note: See TracBrowser for help on using the repository browser.