busybox/util-linux/volume_id/unused_msdos.c
<<
>>
Prefs
   1/*
   2 * volume_id - reads filesystem label and uuid
   3 *
   4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
   5 *
   6 *      This library is free software; you can redistribute it and/or
   7 *      modify it under the terms of the GNU Lesser General Public
   8 *      License as published by the Free Software Foundation; either
   9 *      version 2.1 of the License, or (at your option) any later version.
  10 *
  11 *      This library is distributed in the hope that it will be useful,
  12 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 *      Lesser General Public License for more details.
  15 *
  16 *      You should have received a copy of the GNU Lesser General Public
  17 *      License along with this library; if not, write to the Free Software
  18 *      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 */
  20//config:### config FEATURE_VOLUMEID_MSDOS
  21//config:###    bool "msdos filesystem"
  22//config:###    default y
  23//config:###    depends on VOLUMEID
  24
  25//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o
  26
  27#include "volume_id_internal.h"
  28
  29struct msdos_partition_entry {
  30        uint8_t         boot_ind;
  31        uint8_t         head;
  32        uint8_t         sector;
  33        uint8_t         cyl;
  34        uint8_t         sys_ind;
  35        uint8_t         end_head;
  36        uint8_t         end_sector;
  37        uint8_t         end_cyl;
  38        uint32_t        start_sect;
  39        uint32_t        nr_sects;
  40} PACKED;
  41
  42#define MSDOS_PARTTABLE_OFFSET          0x1be
  43#define MSDOS_SIG_OFF                   0x1fe
  44#define BSIZE                           0x200
  45#define DOS_EXTENDED_PARTITION          0x05
  46#define LINUX_EXTENDED_PARTITION        0x85
  47#define WIN98_EXTENDED_PARTITION        0x0f
  48#define LINUX_RAID_PARTITION            0xfd
  49#define is_extended(type) \
  50        (type == DOS_EXTENDED_PARTITION ||      \
  51         type == WIN98_EXTENDED_PARTITION ||    \
  52         type == LINUX_EXTENDED_PARTITION)
  53#define is_raid(type) \
  54        (type == LINUX_RAID_PARTITION)
  55
  56int FAST_FUNC volume_id_probe_msdos_part_table(struct volume_id *id, uint64_t off)
  57{
  58        const uint8_t *buf;
  59        int i;
  60        uint64_t poff;
  61        uint64_t plen;
  62        uint64_t extended = 0;
  63        uint64_t current;
  64        uint64_t next;
  65        int limit;
  66        int empty = 1;
  67        struct msdos_partition_entry *part;
  68        struct volume_id_partition *p;
  69
  70        dbg("probing at offset 0x%llx", (unsigned long long) off);
  71
  72        buf = volume_id_get_buffer(id, off, 0x200);
  73        if (buf == NULL)
  74                return -1;
  75
  76        if (buf[MSDOS_SIG_OFF] != 0x55 || buf[MSDOS_SIG_OFF + 1] != 0xaa)
  77                return -1;
  78
  79        /* check flags on all entries for a valid partition table */
  80        part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
  81        for (i = 0; i < 4; i++) {
  82                if (part[i].boot_ind != 0
  83                 && part[i].boot_ind != 0x80
  84                ) {
  85                        return -1;
  86                }
  87
  88                if (part[i].nr_sects != 0)
  89                        empty = 0;
  90        }
  91        if (empty == 1)
  92                return -1;
  93
  94        if (id->partitions != NULL)
  95                free(id->partitions);
  96        id->partitions = xzalloc(VOLUME_ID_PARTITIONS_MAX *
  97                                sizeof(struct volume_id_partition));
  98
  99        for (i = 0; i < 4; i++) {
 100                poff = (uint64_t) le32_to_cpu(part[i].start_sect) * BSIZE;
 101                plen = (uint64_t) le32_to_cpu(part[i].nr_sects) * BSIZE;
 102
 103                if (plen == 0)
 104                        continue;
 105
 106                p = &id->partitions[i];
 107
 108//              p->pt_type_raw = part[i].sys_ind;
 109
 110                if (is_extended(part[i].sys_ind)) {
 111                        dbg("found extended partition at 0x%llx", (unsigned long long) poff);
 112//                      volume_id_set_usage_part(p, VOLUME_ID_PARTITIONTABLE);
 113//                      p->type = "msdos_extended_partition";
 114                        if (extended == 0)
 115                                extended = off + poff;
 116                } else {
 117                        dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
 118                                part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen);
 119
 120//                      if (is_raid(part[i].sys_ind))
 121//                              volume_id_set_usage_part(p, VOLUME_ID_RAID);
 122//                      else
 123//                              volume_id_set_usage_part(p, VOLUME_ID_UNPROBED);
 124                }
 125
 126//              p->pt_off = off + poff;
 127//              p->pt_len = plen;
 128                id->partition_count = i+1;
 129        }
 130
 131        next = extended;
 132        current = extended;
 133        limit = 50;
 134
 135        /* follow extended partition chain and add data partitions */
 136        while (next != 0) {
 137                if (limit-- == 0) {
 138                        dbg("extended chain limit reached");
 139                        break;
 140                }
 141
 142                buf = volume_id_get_buffer(id, current, 0x200);
 143                if (buf == NULL)
 144                        break;
 145
 146                part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
 147
 148                if (buf[MSDOS_SIG_OFF] != 0x55 || buf[MSDOS_SIG_OFF + 1] != 0xaa)
 149                        break;
 150
 151                next = 0;
 152
 153                for (i = 0; i < 4; i++) {
 154                        poff = (uint64_t) le32_to_cpu(part[i].start_sect) * BSIZE;
 155                        plen = (uint64_t) le32_to_cpu(part[i].nr_sects) * BSIZE;
 156
 157                        if (plen == 0)
 158                                continue;
 159
 160                        if (is_extended(part[i].sys_ind)) {
 161                                dbg("found extended partition at 0x%llx", (unsigned long long) poff);
 162                                if (next == 0)
 163                                        next = extended + poff;
 164                        } else {
 165                                dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
 166                                        part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen);
 167
 168                                /* we always start at the 5th entry */
 169//                              while (id->partition_count < 4)
 170//                                      volume_id_set_usage_part(&id->partitions[id->partition_count++], VOLUME_ID_UNUSED);
 171                                if (id->partition_count < 4)
 172                                        id->partition_count = 4;
 173
 174//                              p = &id->partitions[id->partition_count];
 175
 176//                              if (is_raid(part[i].sys_ind))
 177//                                      volume_id_set_usage_part(p, VOLUME_ID_RAID);
 178//                              else
 179//                                      volume_id_set_usage_part(p, VOLUME_ID_UNPROBED);
 180
 181//                              p->pt_off = current + poff;
 182//                              p->pt_len = plen;
 183                                id->partition_count++;
 184
 185//                              p->pt_type_raw = part[i].sys_ind;
 186
 187                                if (id->partition_count >= VOLUME_ID_PARTITIONS_MAX) {
 188                                        dbg("too many partitions");
 189                                        next = 0;
 190                                }
 191                        }
 192                }
 193
 194                current = next;
 195        }
 196
 197//      volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
 198//      id->type = "msdos_partition_table";
 199
 200        return 0;
 201}
 202