source: rtems/cpukit/libblock/src/ide_part_table.c @ 0d15414e

4.104.115
Last change on this file since 0d15414e was 7baa484, checked in by Chris Johns <chrisj@…>, on Jun 12, 2009 at 1:53:33 AM

2009-06-12 Chris Johns <chrisj@…>

  • libblock/src/bdbuf.c: Update comments.
  • libblock/src/bdpart.c, libblock/src/ide_part_table.c: Get the device from the rdev field of the stat buf.
  • libcsupport/include/rtems/libio.h: Add a path length to evalpath handler. Add parent locations to rmmod and unlink handlers.
  • libcsupport/include/rtems/libio_.h: Add a path length to rtems_filesystem_evaluate_path. Add rtems_filesystem_evaluate_relative_path, rtems_filesystem_dirname, and rtems_filesystem_prefix_separators. Remove rtems_filesystem_evaluate_parent.
  • libcsupport/src/base_fs.c, libcsupport/src/chdir.c, libcsupport/src/chmod.c, libcsupport/src/chown.c, libcsupport/src/chroot.c, libcsupport/src/fchdir.c, libcsupport/src/link.c, libcsupport/src/mount.c, libcsupport/src/open.c, libcsupport/src/privateenv.c, libcsupport/src/readlink.c, libcsupport/src/unmount.c, libcsupport/src/utime.c, libcsupport/src/unmount.c, libcsupport/src/utime.c, libfs/src/devfs/devfs.h, libfs/src/devfs/devfs_eval.c, libfs/src/devfs/devstat.c, libfs/src/dosfs/msdos_create.c, libfs/src/dosfs/msdos_misc.c, libfs/src/imfs/imfs.h, libfs/src/imfs/imfs_eval.c, libfs/src/imfs/imfs_load_tar.c, libfs/src/imfs/ioman.c, libfs/src/pipe/pipe.c, libmisc/fsmount/fsmount.c, libnetworking/lib/ftpfs.c: Add the length parameter to the eval call.
  • libcsupport/src/eval.c: Add rtems_filesystem_prefix_separators, rtems_filesystem_dirname, rtems_filesystem_evaluate_relative_path. Add the length parameter to the eval call.
  • libcsupport/src/rmdir.c: Find the parent pathloc then the node pathloc from that node. Remove the call to find the parent given the node pathloc.
  • libcsupport/src/stat.c: Add the length parameter to the eval call. Set the device into the rdev field.
  • libcsupport/src/unlink.c: Find the parent pathloc then the node pathloc from that node. Remove the call to find the parent given the node pathloc.
  • libfs/src/dosfs/fat.c, libfs/src/dosfs/msdos_format.c: Get the disk device number from the stat rdev field.
  • libfs/src/dosfs/msdos.h: Add the length parameter to the eval call. Add the parent pathloc to the rmnod handler.
  • libfs/src/dosfs/msdos_dir.c: Add the parent pathloc to the rmnod handler.
  • libfs/src/dosfs/msdos_eval.c: Add the length parameter to the eval and token call.
  • libfs/src/imfs/imfs_directory.c: Add the parent pathloc to the rmnod handler.
  • libfs/src/imfs/imfs_fchmod.c: Do not test the mode flags for only the allowed flags. Add the missing flags spec'ed in the POSIX standard.
  • libfs/src/imfs/imfs_fsunmount.c, libfs/src/imfs/imfs_rmnod.c, libfs/src/imfs/imfs_unlink.c, libfs/src/imfs/memfile.c: Add the parent node. Currently ignored in the IMFS.
  • libfs/src/imfs/imfs_stat.c: Return the device number in the rdev field.
  • libfs/src/imfs/imfs_mknod.c, libfs/src/imfs/imfs_symlink.c : Add the length parameter to the token call.
  • libfs/src/nfsclient/src/nfs.c: Add the length parameter to the eval call and parent node to the rmnod and unlink command.
  • libmisc/shell/internal.h: Remove the libc mounter decl to make public.
  • libmisc/shell/main_mount.c: Add support for hooking external mount support for new file systems.
  • libmisc/shell/shell.h: Add helper functions for the mount command.
  • Property mode set to 100644
File size: 14.0 KB
Line 
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
15 *  http://www.rtems.com/license/LICENSE.
16 *
17 * $Id$
18 *
19 *****************************************************************************/
20
21#if HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include <string.h>
26
27#include <rtems/ide_part_table.h>
28
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
49get_sector(dev_t dev, uint32_t sector_num, rtems_sector_data_t **sector)
50{
51    rtems_sector_data_t *s;
52    rtems_bdbuf_buffer  *buf;
53    rtems_status_code    rc;
54
55    if (sector == NULL)
56    {
57        return RTEMS_INTERNAL_ERROR;
58    }
59
60    s = (rtems_sector_data_t *) malloc(sizeof(rtems_sector_data_t) + RTEMS_IDE_SECTOR_SIZE);
61    if (s == NULL)
62    {
63        return RTEMS_NO_MEMORY;
64    }
65
66    rc = rtems_bdbuf_read(dev, sector_num, &buf);
67    if (rc != RTEMS_SUCCESSFUL)
68    {
69        free(s);
70        return rc;
71    }
72
73    memcpy(s->data, buf->buffer, RTEMS_IDE_SECTOR_SIZE);
74    s->sector_num = sector_num;
75
76    *sector = s;
77
78    rtems_bdbuf_release(buf);
79
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:
92 *      true if sector has msdos signature, false otherwise
93 */
94static bool
95msdos_signature_check (rtems_sector_data_t *sector)
96{
97    uint8_t *p = sector->data + RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_OFFSET;
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:
112 *      true if partition type is extended, false otherwise
113 */
114static bool
115is_extended(uint8_t type)
116{
117    return ((type == EXTENDED_PARTITION) || (type == LINUX_EXTENDED));
118}
119
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:
128 *      true if partition type is extended, false otherwise
129 */
130static bool
131is_fat_partition(uint8_t type)
132{
133  static const uint8_t fat_part_types[] = {
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
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
159data_to_part_desc(uint8_t *data, rtems_part_desc_t **new_part_desc)
160{
161    rtems_part_desc_t *part_desc;
162    uint32_t           temp;
163
164    if (new_part_desc == NULL)
165    {
166        return RTEMS_INTERNAL_ERROR;
167    }
168
169    *new_part_desc = NULL;
170
171    if ((part_desc = calloc(1, sizeof(rtems_part_desc_t))) == NULL)
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 */
182    memcpy(&temp, data + RTEMS_IDE_PARTITION_START_OFFSET, sizeof(uint32_t));
183    part_desc->start = LE_TO_CPU_U32(temp);
184
185    memcpy(&temp, data + RTEMS_IDE_PARTITION_SIZE_OFFSET, sizeof(uint32_t));
186    part_desc->size = LE_TO_CPU_U32(temp);
187
188    /*
189     * use partitions that are
190     * - extended
191     * or
192     * - FAT type and non-zero
193     */
194    if (is_extended(part_desc->sys_type) ||
195        ((is_fat_partition(part_desc->sys_type)) && (part_desc->size != 0))) {
196      *new_part_desc = part_desc;
197    }
198    else {
199      /* empty partition */
200      free(part_desc);
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:
212 *      start    - start sector of primary extended partition, used for
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
222read_extended_partition(uint32_t start, rtems_part_desc_t *ext_part)
223{
224    int                  i;
225    dev_t                dev;
226    rtems_sector_data_t *sector;
227    uint32_t             here;
228    uint8_t             *data;
229    rtems_part_desc_t   *new_part_desc;
230    rtems_status_code    rc;
231
232    if ((ext_part == NULL) || (ext_part->disk_desc == NULL))
233    {
234        return RTEMS_INTERNAL_ERROR;
235    }
236
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    {
247        return rc;
248    }
249
250    if (!msdos_signature_check(sector))
251    {
252        return RTEMS_INTERNAL_ERROR;
253    }
254
255    /* read and process up to 4 logical partition descriptors */
256
257    data = sector->data + RTEMS_IDE_PARTITION_TABLE_OFFSET;
258
259    for (i = 0; i < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER; i++)
260    {
261        /* if data_to_part_desc fails skip this partition
262         * and parse the next one
263         */
264        rc = data_to_part_desc(data, &new_part_desc);
265        if (rc != RTEMS_SUCCESSFUL)
266        {
267            free(sector);
268            return rc;
269        }
270
271        if (new_part_desc == NULL)
272        {
273            data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE;
274            continue;
275        }
276
277        ext_part->sub_part[i] = new_part_desc;
278        new_part_desc->ext_part = ext_part;
279        new_part_desc->disk_desc = ext_part->disk_desc;
280
281        if (is_extended(new_part_desc->sys_type))
282        {
283            new_part_desc->log_id = EMPTY_PARTITION;
284            new_part_desc->start += start;
285            read_extended_partition(start, new_part_desc);
286        }
287        else
288        {
289            rtems_disk_desc_t *disk_desc = new_part_desc->disk_desc;
290            disk_desc->partitions[disk_desc->last_log_id] = new_part_desc;
291            new_part_desc->log_id = ++disk_desc->last_log_id;
292            new_part_desc->start += here;
293            new_part_desc->end = new_part_desc->start + new_part_desc->size - 1;
294        }
295        data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE;
296    }
297
298    free(sector);
299
300    return RTEMS_SUCCESSFUL;
301}
302
303
304/*
305 * read_mbr --
306 *      reads Master Boot Record (sector 0) of physical device and
307 *      constructs disk description structure
308 *
309 * PARAMETERS:
310 *      disk_desc - returned disc description structure
311 *
312 * RETURNS:
313 *      RTEMS_SUCCESSFUL if success,
314 *      RTEMS_INTERNAL_ERROR otherwise
315 */
316static rtems_status_code
317read_mbr(rtems_disk_desc_t *disk_desc)
318{
319    int                  part_num;
320    rtems_sector_data_t *sector;
321    rtems_part_desc_t   *part_desc;
322    uint8_t             *data;
323    rtems_status_code    rc;
324    dev_t                dev = disk_desc->dev;
325
326    /* get MBR sector */
327    rc = get_sector(dev, 0, &sector);
328    if (rc != RTEMS_SUCCESSFUL)
329    {
330        return rc;
331    }
332
333    /* check if the partition table structure is MS-DOS style */
334    if (!msdos_signature_check(sector))
335    {
336        return RTEMS_INTERNAL_ERROR;
337    }
338
339    /* read and process 4 primary partition descriptors */
340
341    data = sector->data + RTEMS_IDE_PARTITION_TABLE_OFFSET;
342
343    for (part_num = 0;
344         part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
345         part_num++)
346    {
347        rc = data_to_part_desc(data, &part_desc);
348        if (rc != RTEMS_SUCCESSFUL)
349        {
350            free(sector);
351            return rc;
352        }
353
354        if (part_desc != NULL)
355        {
356            part_desc->log_id = part_num + 1;
357            part_desc->disk_desc = disk_desc;
358            part_desc->end = part_desc->start + part_desc->size - 1;
359            disk_desc->partitions[part_num] = part_desc;
360        }
361        else
362        {
363            disk_desc->partitions[part_num] = NULL;
364        }
365
366        data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE;
367    }
368
369    free(sector);
370
371    disk_desc->last_log_id = RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
372
373    /* There cannot be more than one extended partition,
374       but we are to process each primary partition */
375    for (part_num = 0;
376         part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
377         part_num++)
378    {
379        part_desc = disk_desc->partitions[part_num];
380        if (part_desc != NULL && is_extended(part_desc->sys_type))
381        {
382            read_extended_partition(part_desc->start, part_desc);
383        }
384    }
385
386    return RTEMS_SUCCESSFUL;
387}
388
389
390/*
391 * partition free --
392 *      frees partition description structure
393 *
394 * PARAMETERS:
395 *      part_desc - returned disc description structure
396 *
397 * RETURNS:
398 *      N/A
399 */
400static void
401partition_free(rtems_part_desc_t *part_desc)
402{
403    int part_num;
404
405    if (part_desc == NULL)
406        return;
407
408    if (is_extended(part_desc->sys_type))
409    {
410        for (part_num = 0;
411             part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
412             part_num++)
413        {
414            partition_free(part_desc->sub_part[part_num]);
415        }
416    }
417
418    free(part_desc);
419}
420
421
422/*
423 * rtems_ide_part_table_free - frees disk descriptor structure
424 *
425 * PARAMETERS:
426 *      disk_desc - disc descriptor structure to free
427 *
428 * RETURNS:
429 *      N/A
430 */
431void
432rtems_ide_part_table_free(rtems_disk_desc_t *disk_desc)
433{
434    int part_num;
435
436    for (part_num = 0; part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER; part_num++)
437    {
438        partition_free(disk_desc->partitions[part_num]);
439    }
440
441    free(disk_desc);
442}
443
444
445/*
446 * rtems_ide_part_table_get - reads partition table structure from the device
447 *                            and creates disk description structure
448 *
449 * PARAMETERS:
450 *      dev_name - path to physical device in /dev filesystem
451 *      disk_desc       - returned disc description structure
452 *
453 * RETURNS:
454 *      RTEMS_SUCCESSFUL if success,
455 *      RTEMS_INTERNAL_ERROR otherwise
456 */
457rtems_status_code
458rtems_ide_part_table_get(const char *dev_name, rtems_disk_desc_t *disk_desc)
459{
460    struct stat         dev_stat;
461    rtems_status_code   rc;
462
463    rc = stat(dev_name, &dev_stat);
464    if (rc != RTEMS_SUCCESSFUL)
465    {
466        return RTEMS_INTERNAL_ERROR;
467    }
468
469    strncpy (disk_desc->dev_name, dev_name, 15);
470    disk_desc->dev = dev_stat.st_rdev;
471    disk_desc->sector_size = (dev_stat.st_blksize) ? dev_stat.st_blksize :
472                                              RTEMS_IDE_SECTOR_SIZE;
473
474    rc = read_mbr(disk_desc);
475
476    return rc;
477}
478
479
480/*
481 * rtems_ide_part_table_initialize - initializes logical devices
482 *                                   on the physical IDE drive
483 *
484 * PARAMETERS:
485 *      dev_name - path to physical device in /dev filesystem
486 *
487 * RETURNS:
488 *      RTEMS_SUCCESSFUL if success,
489 *      RTEMS_NO_MEMOTY if cannot have not enough memory,
490 *      RTEMS_INTERNAL_ERROR if other error occurs.
491 */
492rtems_status_code
493rtems_ide_part_table_initialize(char *dev_name)
494{
495    int                         part_num;
496    dev_t                       dev;
497    rtems_disk_desc_t          *disk_desc;
498    rtems_device_major_number   major;
499    rtems_device_minor_number   minor;
500    rtems_status_code           rc;
501    rtems_part_desc_t          *part_desc;
502
503    /* logical device name /dev/hdxyy */
504    char                        name[RTEMS_IDE_PARTITION_DEV_NAME_LENGTH_MAX];
505
506    disk_desc = (rtems_disk_desc_t *) calloc(1, sizeof(rtems_disk_desc_t));
507    if (disk_desc == NULL)
508    {
509        return RTEMS_NO_MEMORY;
510    }
511
512    /* get partition table */
513    rc = rtems_ide_part_table_get(dev_name, disk_desc);
514    if (rc != RTEMS_SUCCESSFUL)
515    {
516        return rc;
517    }
518
519    /* To avoid device numbers conflicts we have to use for logic disk the same
520     * device major number as ATA device has, and minor number that equals to
521     * sum of logic disk partition number and the minor number of physical disk
522     */
523
524    rtems_filesystem_split_dev_t (disk_desc->dev, major, minor);
525
526    /* create logical disks on the physical one */
527    for (part_num = 0; part_num < disk_desc->last_log_id; part_num++)
528    {
529        sprintf(name, "%s%d", dev_name, part_num + 1);
530        dev = rtems_filesystem_make_dev_t(major, ++minor);
531
532        part_desc = disk_desc->partitions[part_num];
533        if (part_desc == NULL)
534        {
535            continue;
536        }
537
538        rc = rtems_disk_create_log(dev, disk_desc->dev, part_desc->start,
539                                   part_desc->size, name);
540        if (rc != RTEMS_SUCCESSFUL)
541        {
542            fprintf(stdout,"Cannot create device %s, error code %d\n", name, rc);
543            continue;
544        }
545    }
546
547    rtems_ide_part_table_free(disk_desc);
548
549    return RTEMS_SUCCESSFUL;
550}
Note: See TracBrowser for help on using the repository browser.