part_dos.c 7.5 KB
Newer Older
W
wdenk 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
/*
 * (C) Copyright 2001
 * Raymond Lo, lo@routefree.com
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

/*
 * Support for harddisk partitions.
 *
 * To be compatible with LinuxPPC and Apple we use the standard Apple
 * SCSI disk partitioning scheme. For more information see:
 * http://developer.apple.com/techpubs/mac/Devices/Devices-126.html#MARKER-14-92
 */

#include <common.h>
#include <command.h>
#include <ide.h>
#include "part_dos.h"

38 39 40 41 42 43
#if defined(CONFIG_CMD_IDE) || \
    defined(CONFIG_CMD_SATA) || \
    defined(CONFIG_CMD_SCSI) || \
    defined(CONFIG_CMD_USB) || \
    defined(CONFIG_MMC) || \
    defined(CONFIG_SYSTEMACE)
W
wdenk 已提交
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

/* Convert char[4] in little endian format to the host format integer
 */
static inline int le32_to_int(unsigned char *le32)
{
    return ((le32[3] << 24) +
	    (le32[2] << 16) +
	    (le32[1] << 8) +
	     le32[0]
	   );
}

static inline int is_extended(int part_type)
{
    return (part_type == 0x5 ||
	    part_type == 0xf ||
	    part_type == 0x85);
}

63 64 65 66 67
static inline int is_bootable(dos_partition_t *p)
{
	return p->boot_ind == 0x80;
}

W
wdenk 已提交
68 69 70 71 72
static void print_one_part (dos_partition_t *p, int ext_part_sector, int part_num)
{
	int lba_start = ext_part_sector + le32_to_int (p->start4);
	int lba_size  = le32_to_int (p->size4);

73
	printf("%5d\t\t%10d\t%10d\t%2x%s%s\n",
W
wdenk 已提交
74
		part_num, lba_start, lba_size, p->sys_ind,
75 76
		(is_extended(p->sys_ind) ? " Extd" : ""),
		(is_bootable(p) ? " Boot" : ""));
W
wdenk 已提交
77 78
}

W
wdenk 已提交
79 80 81 82 83 84
static int test_block_type(unsigned char *buffer)
{
	if((buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||
	    (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {
		return (-1);
	} /* no DOS Signature at all */
85 86
	if (strncmp((char *)&buffer[DOS_PBR_FSTYPE_OFFSET],"FAT",3)==0 ||
	    strncmp((char *)&buffer[DOS_PBR32_FSTYPE_OFFSET],"FAT32",5)==0) {
W
wdenk 已提交
87
		return DOS_PBR; /* is PBR */
88
	}
W
wdenk 已提交
89 90 91
	return DOS_MBR;	    /* Is MBR */
}

W
wdenk 已提交
92 93 94

int test_part_dos (block_dev_desc_t *dev_desc)
{
95
	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
W
wdenk 已提交
96 97 98 99

	if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *) buffer) != 1) ||
	    (buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||
	    (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {
W
wdenk 已提交
100
		return (-1);
W
wdenk 已提交
101 102 103 104 105 106 107 108 109
	}
	return (0);
}

/*  Print a partition that is relative to its Extended partition table
 */
static void print_partition_extended (block_dev_desc_t *dev_desc, int ext_part_sector, int relative,
							   int part_num)
{
110
	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
W
wdenk 已提交
111 112 113 114 115 116 117 118
	dos_partition_t *pt;
	int i;

	if (dev_desc->block_read(dev_desc->dev, ext_part_sector, 1, (ulong *) buffer) != 1) {
		printf ("** Can't read partition table on %d:%d **\n",
			dev_desc->dev, ext_part_sector);
		return;
	}
W
wdenk 已提交
119 120
	i=test_block_type(buffer);
	if(i==-1) {
W
wdenk 已提交
121 122 123 124 125
		printf ("bad MBR sector signature 0x%02x%02x\n",
			buffer[DOS_PART_MAGIC_OFFSET],
			buffer[DOS_PART_MAGIC_OFFSET + 1]);
		return;
	}
W
wdenk 已提交
126 127 128 129 130
	if(i==DOS_PBR) {
		printf ("    1\t\t         0\t%10ld\t%2x\n",
			dev_desc->lba, buffer[DOS_PBR_MEDIA_TYPE_OFFSET]);
		return;
	}
W
wdenk 已提交
131 132 133 134
	/* Print all primary/logical partitions */
	pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
	for (i = 0; i < 4; i++, pt++) {
		/*
W
wdenk 已提交
135
		 * fdisk does not show the extended partitions that
W
wdenk 已提交
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
		 * are not in the MBR
		 */

		if ((pt->sys_ind != 0) &&
		    (ext_part_sector == 0 || !is_extended (pt->sys_ind)) ) {
			print_one_part (pt, ext_part_sector, part_num);
		}

		/* Reverse engr the fdisk part# assignment rule! */
		if ((ext_part_sector == 0) ||
		    (pt->sys_ind != 0 && !is_extended (pt->sys_ind)) ) {
			part_num++;
		}
	}

	/* Follows the extended partitions */
	pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
	for (i = 0; i < 4; i++, pt++) {
		if (is_extended (pt->sys_ind)) {
			int lba_start = le32_to_int (pt->start4) + relative;

			print_partition_extended (dev_desc, lba_start,
						  ext_part_sector == 0  ? lba_start
									: relative,
						  part_num);
		}
	}

	return;
}


/*  Print a partition that is relative to its Extended partition table
 */
static int get_partition_info_extended (block_dev_desc_t *dev_desc, int ext_part_sector,
				 int relative, int part_num,
				 int which_part, disk_partition_t *info)
{
174
	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
W
wdenk 已提交
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
	dos_partition_t *pt;
	int i;

	if (dev_desc->block_read (dev_desc->dev, ext_part_sector, 1, (ulong *) buffer) != 1) {
		printf ("** Can't read partition table on %d:%d **\n",
			dev_desc->dev, ext_part_sector);
		return -1;
	}
	if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
		buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) {
		printf ("bad MBR sector signature 0x%02x%02x\n",
			buffer[DOS_PART_MAGIC_OFFSET],
			buffer[DOS_PART_MAGIC_OFFSET + 1]);
		return -1;
	}

	/* Print all primary/logical partitions */
	pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
	for (i = 0; i < 4; i++, pt++) {
		/*
W
wdenk 已提交
195 196
		 * fdisk does not show the extended partitions that
		 * are not in the MBR
W
wdenk 已提交
197
		 */
198 199
		if (((pt->boot_ind & ~0x80) == 0) &&
		    (pt->sys_ind != 0) &&
W
wdenk 已提交
200 201
		    (part_num == which_part) &&
		    (is_extended(pt->sys_ind) == 0)) {
W
wdenk 已提交
202 203 204 205 206
			info->blksz = 512;
			info->start = ext_part_sector + le32_to_int (pt->start4);
			info->size  = le32_to_int (pt->size4);
			switch(dev_desc->if_type) {
				case IF_TYPE_IDE:
207
				case IF_TYPE_SATA:
W
wdenk 已提交
208
				case IF_TYPE_ATAPI:
209 210
					sprintf ((char *)info->name, "hd%c%d",
						'a' + dev_desc->dev, part_num);
W
wdenk 已提交
211 212
					break;
				case IF_TYPE_SCSI:
213 214
					sprintf ((char *)info->name, "sd%c%d",
						'a' + dev_desc->dev, part_num);
W
wdenk 已提交
215 216
					break;
				case IF_TYPE_USB:
217 218
					sprintf ((char *)info->name, "usbd%c%d",
						'a' + dev_desc->dev, part_num);
W
wdenk 已提交
219 220
					break;
				case IF_TYPE_DOC:
221 222
					sprintf ((char *)info->name, "docd%c%d",
						'a' + dev_desc->dev, part_num);
W
wdenk 已提交
223 224
					break;
				default:
225 226
					sprintf ((char *)info->name, "xx%c%d",
						'a' + dev_desc->dev, part_num);
W
wdenk 已提交
227 228 229
					break;
			}
			/* sprintf(info->type, "%d, pt->sys_ind); */
W
Wolfgang Denk 已提交
230
			sprintf ((char *)info->type, "U-Boot");
231
			info->bootable = is_bootable(pt);
W
wdenk 已提交
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
			return 0;
		}

		/* Reverse engr the fdisk part# assignment rule! */
		if ((ext_part_sector == 0) ||
		    (pt->sys_ind != 0 && !is_extended (pt->sys_ind)) ) {
			part_num++;
		}
	}

	/* Follows the extended partitions */
	pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
	for (i = 0; i < 4; i++, pt++) {
		if (is_extended (pt->sys_ind)) {
			int lba_start = le32_to_int (pt->start4) + relative;

			return get_partition_info_extended (dev_desc, lba_start,
				 ext_part_sector == 0 ? lba_start : relative,
				 part_num, which_part, info);
		}
	}
	return -1;
}

void print_part_dos (block_dev_desc_t *dev_desc)
{
	printf ("Partition     Start Sector     Num Sectors     Type\n");
	print_partition_extended (dev_desc, 0, 0, 1);
}

int get_partition_info_dos (block_dev_desc_t *dev_desc, int part, disk_partition_t * info)
{
	return get_partition_info_extended (dev_desc, 0, 0, 1, part, info);
}


268
#endif