uboot/disk/part_dos.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   3 * Raymond Lo, lo@routefree.com
   4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation; either version 2 of
  12 * the License, or (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22 * MA 02111-1307 USA
  23 */
  24
  25/*
  26 * Support for harddisk partitions.
  27 *
  28 * To be compatible with LinuxPPC and Apple we use the standard Apple
  29 * SCSI disk partitioning scheme. For more information see:
  30 * http://developer.apple.com/techpubs/mac/Devices/Devices-126.html#MARKER-14-92
  31 */
  32
  33#include <common.h>
  34#include <command.h>
  35#include <ide.h>
  36#include "part_dos.h"
  37
  38#if defined(CONFIG_CMD_IDE) || \
  39    defined(CONFIG_CMD_SATA) || \
  40    defined(CONFIG_CMD_SCSI) || \
  41    defined(CONFIG_CMD_USB) || \
  42    defined(CONFIG_MMC) || \
  43    defined(CONFIG_SYSTEMACE)
  44
  45/* Convert char[4] in little endian format to the host format integer
  46 */
  47static inline int le32_to_int(unsigned char *le32)
  48{
  49    return ((le32[3] << 24) +
  50            (le32[2] << 16) +
  51            (le32[1] << 8) +
  52             le32[0]
  53           );
  54}
  55
  56static inline int is_extended(int part_type)
  57{
  58    return (part_type == 0x5 ||
  59            part_type == 0xf ||
  60            part_type == 0x85);
  61}
  62
  63static void print_one_part (dos_partition_t *p, int ext_part_sector, int part_num)
  64{
  65        int lba_start = ext_part_sector + le32_to_int (p->start4);
  66        int lba_size  = le32_to_int (p->size4);
  67
  68        printf ("%5d\t\t%10d\t%10d\t%2x%s\n",
  69                part_num, lba_start, lba_size, p->sys_ind,
  70                (is_extended (p->sys_ind) ? " Extd" : ""));
  71}
  72
  73static int test_block_type(unsigned char *buffer)
  74{
  75        if((buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||
  76            (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {
  77                return (-1);
  78        } /* no DOS Signature at all */
  79        if (strncmp((char *)&buffer[DOS_PBR_FSTYPE_OFFSET],"FAT",3)==0 ||
  80            strncmp((char *)&buffer[DOS_PBR32_FSTYPE_OFFSET],"FAT32",5)==0) {
  81                return DOS_PBR; /* is PBR */
  82        }
  83        return DOS_MBR;     /* Is MBR */
  84}
  85
  86
  87int test_part_dos (block_dev_desc_t *dev_desc)
  88{
  89        ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
  90
  91        if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *) buffer) != 1) ||
  92            (buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||
  93            (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {
  94                return (-1);
  95        }
  96        return (0);
  97}
  98
  99/*  Print a partition that is relative to its Extended partition table
 100 */
 101static void print_partition_extended (block_dev_desc_t *dev_desc, int ext_part_sector, int relative,
 102                                                           int part_num)
 103{
 104        ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
 105        dos_partition_t *pt;
 106        int i;
 107
 108        if (dev_desc->block_read(dev_desc->dev, ext_part_sector, 1, (ulong *) buffer) != 1) {
 109                printf ("** Can't read partition table on %d:%d **\n",
 110                        dev_desc->dev, ext_part_sector);
 111                return;
 112        }
 113        i=test_block_type(buffer);
 114        if(i==-1) {
 115                printf ("bad MBR sector signature 0x%02x%02x\n",
 116                        buffer[DOS_PART_MAGIC_OFFSET],
 117                        buffer[DOS_PART_MAGIC_OFFSET + 1]);
 118                return;
 119        }
 120        if(i==DOS_PBR) {
 121                printf ("    1\t\t         0\t%10ld\t%2x\n",
 122                        dev_desc->lba, buffer[DOS_PBR_MEDIA_TYPE_OFFSET]);
 123                return;
 124        }
 125        /* Print all primary/logical partitions */
 126        pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
 127        for (i = 0; i < 4; i++, pt++) {
 128                /*
 129                 * fdisk does not show the extended partitions that
 130                 * are not in the MBR
 131                 */
 132
 133                if ((pt->sys_ind != 0) &&
 134                    (ext_part_sector == 0 || !is_extended (pt->sys_ind)) ) {
 135                        print_one_part (pt, ext_part_sector, part_num);
 136                }
 137
 138                /* Reverse engr the fdisk part# assignment rule! */
 139                if ((ext_part_sector == 0) ||
 140                    (pt->sys_ind != 0 && !is_extended (pt->sys_ind)) ) {
 141                        part_num++;
 142                }
 143        }
 144
 145        /* Follows the extended partitions */
 146        pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
 147        for (i = 0; i < 4; i++, pt++) {
 148                if (is_extended (pt->sys_ind)) {
 149                        int lba_start = le32_to_int (pt->start4) + relative;
 150
 151                        print_partition_extended (dev_desc, lba_start,
 152                                                  ext_part_sector == 0  ? lba_start
 153                                                                        : relative,
 154                                                  part_num);
 155                }
 156        }
 157
 158        return;
 159}
 160
 161
 162/*  Print a partition that is relative to its Extended partition table
 163 */
 164static int get_partition_info_extended (block_dev_desc_t *dev_desc, int ext_part_sector,
 165                                 int relative, int part_num,
 166                                 int which_part, disk_partition_t *info)
 167{
 168        ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
 169        dos_partition_t *pt;
 170        int i;
 171
 172        if (dev_desc->block_read (dev_desc->dev, ext_part_sector, 1, (ulong *) buffer) != 1) {
 173                printf ("** Can't read partition table on %d:%d **\n",
 174                        dev_desc->dev, ext_part_sector);
 175                return -1;
 176        }
 177        if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
 178                buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) {
 179                printf ("bad MBR sector signature 0x%02x%02x\n",
 180                        buffer[DOS_PART_MAGIC_OFFSET],
 181                        buffer[DOS_PART_MAGIC_OFFSET + 1]);
 182                return -1;
 183        }
 184
 185        /* Print all primary/logical partitions */
 186        pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
 187        for (i = 0; i < 4; i++, pt++) {
 188                /*
 189                 * fdisk does not show the extended partitions that
 190                 * are not in the MBR
 191                 */
 192                if (((pt->boot_ind & ~0x80) == 0) &&
 193                    (pt->sys_ind != 0) &&
 194                    (part_num == which_part) &&
 195                    (is_extended(pt->sys_ind) == 0)) {
 196                        info->blksz = 512;
 197                        info->start = ext_part_sector + le32_to_int (pt->start4);
 198                        info->size  = le32_to_int (pt->size4);
 199                        switch(dev_desc->if_type) {
 200                                case IF_TYPE_IDE:
 201                                case IF_TYPE_SATA:
 202                                case IF_TYPE_ATAPI:
 203                                        sprintf ((char *)info->name, "hd%c%d",
 204                                                'a' + dev_desc->dev, part_num);
 205                                        break;
 206                                case IF_TYPE_SCSI:
 207                                        sprintf ((char *)info->name, "sd%c%d",
 208                                                'a' + dev_desc->dev, part_num);
 209                                        break;
 210                                case IF_TYPE_USB:
 211                                        sprintf ((char *)info->name, "usbd%c%d",
 212                                                'a' + dev_desc->dev, part_num);
 213                                        break;
 214                                case IF_TYPE_DOC:
 215                                        sprintf ((char *)info->name, "docd%c%d",
 216                                                'a' + dev_desc->dev, part_num);
 217                                        break;
 218                                default:
 219                                        sprintf ((char *)info->name, "xx%c%d",
 220                                                'a' + dev_desc->dev, part_num);
 221                                        break;
 222                        }
 223                        /* sprintf(info->type, "%d, pt->sys_ind); */
 224                        sprintf ((char *)info->type, "U-Boot");
 225                        return 0;
 226                }
 227
 228                /* Reverse engr the fdisk part# assignment rule! */
 229                if ((ext_part_sector == 0) ||
 230                    (pt->sys_ind != 0 && !is_extended (pt->sys_ind)) ) {
 231                        part_num++;
 232                }
 233        }
 234
 235        /* Follows the extended partitions */
 236        pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
 237        for (i = 0; i < 4; i++, pt++) {
 238                if (is_extended (pt->sys_ind)) {
 239                        int lba_start = le32_to_int (pt->start4) + relative;
 240
 241                        return get_partition_info_extended (dev_desc, lba_start,
 242                                 ext_part_sector == 0 ? lba_start : relative,
 243                                 part_num, which_part, info);
 244                }
 245        }
 246        return -1;
 247}
 248
 249void print_part_dos (block_dev_desc_t *dev_desc)
 250{
 251        printf ("Partition     Start Sector     Num Sectors     Type\n");
 252        print_partition_extended (dev_desc, 0, 0, 1);
 253}
 254
 255int get_partition_info_dos (block_dev_desc_t *dev_desc, int part, disk_partition_t * info)
 256{
 257        return get_partition_info_extended (dev_desc, 0, 0, 1, part, info);
 258}
 259
 260
 261#endif
 262