summaryrefslogtreecommitdiff
path: root/disk
diff options
context:
space:
mode:
authorAlbert ARIBAUD <albert.u.boot@aribaud.net>2012-09-30 23:49:17 +0200
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>2012-09-30 23:49:17 +0200
commit1c27059a2f7158a9c9a8778535b030935d75179d (patch)
treebf577d5c9f0da21c5d57feed1091214e54c39dec /disk
parent8f0732ac3dc3bdbbcada313dc4b4b38d5d2c376a (diff)
parent4668a086bb0a769b741e3a4ffab85f1c41c7cdb8 (diff)
Merge remote-tracking branch 'u-boot/master'
Diffstat (limited to 'disk')
-rw-r--r--disk/part.c326
-rw-r--r--disk/part_dos.c26
-rw-r--r--disk/part_dos.h2
-rw-r--r--disk/part_efi.c32
-rw-r--r--disk/part_mac.c68
5 files changed, 357 insertions, 97 deletions
diff --git a/disk/part.c b/disk/part.c
index 76f3939..3022969 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -24,6 +24,7 @@
#include <common.h>
#include <command.h>
#include <ide.h>
+#include <malloc.h>
#include <part.h>
#undef PART_DEBUG
@@ -70,7 +71,7 @@ static const struct block_drvr block_drvr[] = {
DECLARE_GLOBAL_DATA_PTR;
-block_dev_desc_t *get_dev(char* ifname, int dev)
+block_dev_desc_t *get_dev(const char *ifname, int dev)
{
const struct block_drvr *drvr = block_drvr;
block_dev_desc_t* (*reloc_get_dev)(int dev);
@@ -97,7 +98,7 @@ block_dev_desc_t *get_dev(char* ifname, int dev)
return NULL;
}
#else
-block_dev_desc_t *get_dev(char* ifname, int dev)
+block_dev_desc_t *get_dev(const char *ifname, int dev)
{
return NULL;
}
@@ -288,64 +289,10 @@ void init_part (block_dev_desc_t * dev_desc)
return;
}
#endif
+ dev_desc->part_type = PART_TYPE_UNKNOWN;
}
-int get_partition_info (block_dev_desc_t *dev_desc, int part
- , disk_partition_t *info)
-{
- switch (dev_desc->part_type) {
-#ifdef CONFIG_MAC_PARTITION
- case PART_TYPE_MAC:
- if (get_partition_info_mac(dev_desc,part,info) == 0) {
- PRINTF ("## Valid MAC partition found ##\n");
- return (0);
- }
- break;
-#endif
-
-#ifdef CONFIG_DOS_PARTITION
- case PART_TYPE_DOS:
- if (get_partition_info_dos(dev_desc,part,info) == 0) {
- PRINTF ("## Valid DOS partition found ##\n");
- return (0);
- }
- break;
-#endif
-
-#ifdef CONFIG_ISO_PARTITION
- case PART_TYPE_ISO:
- if (get_partition_info_iso(dev_desc,part,info) == 0) {
- PRINTF ("## Valid ISO boot partition found ##\n");
- return (0);
- }
- break;
-#endif
-
-#ifdef CONFIG_AMIGA_PARTITION
- case PART_TYPE_AMIGA:
- if (get_partition_info_amiga(dev_desc, part, info) == 0)
- {
- PRINTF ("## Valid Amiga partition found ##\n");
- return (0);
- }
- break;
-#endif
-
-#ifdef CONFIG_EFI_PARTITION
- case PART_TYPE_EFI:
- if (get_partition_info_efi(dev_desc,part,info) == 0) {
- PRINTF ("## Valid EFI partition found ##\n");
- return (0);
- }
- break;
-#endif
- default:
- break;
- }
- return (-1);
-}
-
static void print_part_header (const char *type, block_dev_desc_t * dev_desc)
{
puts ("\nPartition Map for ");
@@ -433,3 +380,268 @@ void print_part (block_dev_desc_t * dev_desc)
#endif
#endif
+
+int get_partition_info(block_dev_desc_t *dev_desc, int part
+ , disk_partition_t *info)
+{
+#if defined(CONFIG_CMD_IDE) || \
+ defined(CONFIG_CMD_SATA) || \
+ defined(CONFIG_CMD_SCSI) || \
+ defined(CONFIG_CMD_USB) || \
+ defined(CONFIG_MMC) || \
+ defined(CONFIG_SYSTEMACE)
+
+#ifdef CONFIG_PARTITION_UUIDS
+ /* The common case is no UUID support */
+ info->uuid[0] = 0;
+#endif
+
+ switch (dev_desc->part_type) {
+#ifdef CONFIG_MAC_PARTITION
+ case PART_TYPE_MAC:
+ if (get_partition_info_mac(dev_desc, part, info) == 0) {
+ PRINTF("## Valid MAC partition found ##\n");
+ return 0;
+ }
+ break;
+#endif
+
+#ifdef CONFIG_DOS_PARTITION
+ case PART_TYPE_DOS:
+ if (get_partition_info_dos(dev_desc, part, info) == 0) {
+ PRINTF("## Valid DOS partition found ##\n");
+ return 0;
+ }
+ break;
+#endif
+
+#ifdef CONFIG_ISO_PARTITION
+ case PART_TYPE_ISO:
+ if (get_partition_info_iso(dev_desc, part, info) == 0) {
+ PRINTF("## Valid ISO boot partition found ##\n");
+ return 0;
+ }
+ break;
+#endif
+
+#ifdef CONFIG_AMIGA_PARTITION
+ case PART_TYPE_AMIGA:
+ if (get_partition_info_amiga(dev_desc, part, info) == 0) {
+ PRINTF("## Valid Amiga partition found ##\n");
+ return 0;
+ }
+ break;
+#endif
+
+#ifdef CONFIG_EFI_PARTITION
+ case PART_TYPE_EFI:
+ if (get_partition_info_efi(dev_desc, part, info) == 0) {
+ PRINTF("## Valid EFI partition found ##\n");
+ return 0;
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+#endif
+
+ return -1;
+}
+
+int get_device(const char *ifname, const char *dev_str,
+ block_dev_desc_t **dev_desc)
+{
+ char *ep;
+ int dev;
+
+ dev = simple_strtoul(dev_str, &ep, 16);
+ if (*ep) {
+ printf("** Bad device specification %s %s **\n",
+ ifname, dev_str);
+ return -1;
+ }
+
+ *dev_desc = get_dev(ifname, dev);
+ if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
+ printf("** Bad device %s %s **\n", ifname, dev_str);
+ return -1;
+ }
+
+ return dev;
+}
+
+#define PART_UNSPECIFIED -2
+#define PART_AUTO -1
+#define MAX_SEARCH_PARTITIONS 16
+int get_device_and_partition(const char *ifname, const char *dev_part_str,
+ block_dev_desc_t **dev_desc,
+ disk_partition_t *info, int allow_whole_dev)
+{
+ int ret = -1;
+ const char *part_str;
+ char *dup_str = NULL;
+ const char *dev_str;
+ int dev;
+ char *ep;
+ int p;
+ int part;
+ disk_partition_t tmpinfo;
+
+ /* If no dev_part_str, use bootdevice environment variable */
+ if (!dev_part_str || !strlen(dev_part_str) ||
+ !strcmp(dev_part_str, "-"))
+ dev_part_str = getenv("bootdevice");
+
+ /* If still no dev_part_str, it's an error */
+ if (!dev_part_str) {
+ printf("** No device specified **\n");
+ goto cleanup;
+ }
+
+ /* Separate device and partition ID specification */
+ part_str = strchr(dev_part_str, ':');
+ if (part_str) {
+ dup_str = strdup(dev_part_str);
+ dup_str[part_str - dev_part_str] = 0;
+ dev_str = dup_str;
+ part_str++;
+ } else {
+ dev_str = dev_part_str;
+ }
+
+ /* Look up the device */
+ dev = get_device(ifname, dev_str, dev_desc);
+ if (dev < 0)
+ goto cleanup;
+
+ /* Convert partition ID string to number */
+ if (!part_str || !*part_str) {
+ part = PART_UNSPECIFIED;
+ } else if (!strcmp(part_str, "auto")) {
+ part = PART_AUTO;
+ } else {
+ /* Something specified -> use exactly that */
+ part = (int)simple_strtoul(part_str, &ep, 16);
+ /*
+ * Less than whole string converted,
+ * or request for whole device, but caller requires partition.
+ */
+ if (*ep || (part == 0 && !allow_whole_dev)) {
+ printf("** Bad partition specification %s %s **\n",
+ ifname, dev_part_str);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * No partition table on device,
+ * or user requested partition 0 (entire device).
+ */
+ if (((*dev_desc)->part_type == PART_TYPE_UNKNOWN) ||
+ (part == 0)) {
+ if (!(*dev_desc)->lba) {
+ printf("** Bad device size - %s %s **\n", ifname,
+ dev_str);
+ goto cleanup;
+ }
+
+ /*
+ * If user specified a partition ID other than 0,
+ * or the calling command only accepts partitions,
+ * it's an error.
+ */
+ if ((part > 0) || (!allow_whole_dev)) {
+ printf("** No partition table - %s %s **\n", ifname,
+ dev_str);
+ goto cleanup;
+ }
+
+ info->start = 0;
+ info->size = (*dev_desc)->lba;
+ info->blksz = (*dev_desc)->blksz;
+ info->bootable = 0;
+#ifdef CONFIG_PARTITION_UUIDS
+ info->uuid[0] = 0;
+#endif
+
+ ret = 0;
+ goto cleanup;
+ }
+
+ /*
+ * Now there's known to be a partition table,
+ * not specifying a partition means to pick partition 1.
+ */
+ if (part == PART_UNSPECIFIED)
+ part = 1;
+
+ /*
+ * If user didn't specify a partition number, or did specify something
+ * other than "auto", use that partition number directly.
+ */
+ if (part != PART_AUTO) {
+ ret = get_partition_info(*dev_desc, part, info);
+ if (ret) {
+ printf("** Invalid partition %d **\n", part);
+ goto cleanup;
+ }
+ } else {
+ /*
+ * Find the first bootable partition.
+ * If none are bootable, fall back to the first valid partition.
+ */
+ part = 0;
+ for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
+ ret = get_partition_info(*dev_desc, p, info);
+ if (ret)
+ continue;
+
+ /*
+ * First valid partition, or new better partition?
+ * If so, save partition ID.
+ */
+ if (!part || info->bootable)
+ part = p;
+
+ /* Best possible partition? Stop searching. */
+ if (info->bootable)
+ break;
+
+ /*
+ * We now need to search further for best possible.
+ * If we what we just queried was the best so far,
+ * save the info since we over-write it next loop.
+ */
+ if (part == p)
+ tmpinfo = *info;
+ }
+ /* If we found any acceptable partition */
+ if (part) {
+ /*
+ * If we searched all possible partition IDs,
+ * return the first valid partition we found.
+ */
+ if (p == MAX_SEARCH_PARTITIONS + 1)
+ *info = tmpinfo;
+ ret = 0;
+ } else {
+ printf("** No valid partitions found **\n");
+ goto cleanup;
+ }
+ }
+ if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) {
+ printf("** Invalid partition type \"%.32s\""
+ " (expect \"" BOOT_PART_TYPE "\")\n",
+ info->type);
+ ret = -1;
+ goto cleanup;
+ }
+
+ ret = part;
+ goto cleanup;
+
+cleanup:
+ free(dup_str);
+ return ret;
+}
diff --git a/disk/part_dos.c b/disk/part_dos.c
index a43dd9c..c9a3e2b 100644
--- a/disk/part_dos.c
+++ b/disk/part_dos.c
@@ -60,14 +60,20 @@ static inline int is_extended(int part_type)
part_type == 0x85);
}
+static inline int is_bootable(dos_partition_t *p)
+{
+ return p->boot_ind == 0x80;
+}
+
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);
- printf ("%5d\t\t%10d\t%10d\t%2x%s\n",
+ printf("%5d\t\t%10d\t%10d\t%2x%s%s\n",
part_num, lba_start, lba_size, p->sys_ind,
- (is_extended (p->sys_ind) ? " Extd" : ""));
+ (is_extended(p->sys_ind) ? " Extd" : ""),
+ (is_bootable(p) ? " Boot" : ""));
}
static int test_block_type(unsigned char *buffer)
@@ -163,7 +169,8 @@ static void print_partition_extended (block_dev_desc_t *dev_desc, int ext_part_s
*/
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)
+ int which_part, disk_partition_t *info,
+ unsigned int disksig)
{
ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
dos_partition_t *pt;
@@ -182,6 +189,11 @@ static int get_partition_info_extended (block_dev_desc_t *dev_desc, int ext_part
return -1;
}
+#ifdef CONFIG_PARTITION_UUIDS
+ if (!ext_part_sector)
+ disksig = le32_to_int(&buffer[DOS_PART_DISKSIG_OFFSET]);
+#endif
+
/* Print all primary/logical partitions */
pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
for (i = 0; i < 4; i++, pt++) {
@@ -222,6 +234,10 @@ static int get_partition_info_extended (block_dev_desc_t *dev_desc, int ext_part
}
/* sprintf(info->type, "%d, pt->sys_ind); */
sprintf ((char *)info->type, "U-Boot");
+ info->bootable = is_bootable(pt);
+#ifdef CONFIG_PARTITION_UUIDS
+ sprintf(info->uuid, "%08x-%02x", disksig, part_num);
+#endif
return 0;
}
@@ -240,7 +256,7 @@ static int get_partition_info_extended (block_dev_desc_t *dev_desc, int ext_part
return get_partition_info_extended (dev_desc, lba_start,
ext_part_sector == 0 ? lba_start : relative,
- part_num, which_part, info);
+ part_num, which_part, info, disksig);
}
}
return -1;
@@ -254,7 +270,7 @@ void print_part_dos (block_dev_desc_t *dev_desc)
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);
+ return get_partition_info_extended(dev_desc, 0, 0, 1, part, info, 0);
}
diff --git a/disk/part_dos.h b/disk/part_dos.h
index de75542..7b77c1d 100644
--- a/disk/part_dos.h
+++ b/disk/part_dos.h
@@ -24,7 +24,7 @@
#ifndef _DISK_PART_DOS_H
#define _DISK_PART_DOS_H
-
+#define DOS_PART_DISKSIG_OFFSET 0x1b8
#define DOS_PART_TBL_OFFSET 0x1be
#define DOS_PART_MAGIC_OFFSET 0x1fe
#define DOS_PBR_FSTYPE_OFFSET 0x36
diff --git a/disk/part_efi.c b/disk/part_efi.c
index 02927a0..264ea9c 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -154,6 +154,28 @@ void print_part_efi(block_dev_desc_t * dev_desc)
return;
}
+#ifdef CONFIG_PARTITION_UUIDS
+static void uuid_string(unsigned char *uuid, char *str)
+{
+ static const u8 le[16] = {3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11,
+ 12, 13, 14, 15};
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ sprintf(str, "%02x", uuid[le[i]]);
+ str += 2;
+ switch (i) {
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ *str++ = '-';
+ break;
+ }
+ }
+}
+#endif
+
int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
disk_partition_t * info)
{
@@ -173,6 +195,13 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
return -1;
}
+ if (part > le32_to_int(gpt_head->num_partition_entries) ||
+ !is_pte_valid(&gpt_pte[part - 1])) {
+ printf("%s: *** ERROR: Invalid partition number %d ***\n",
+ __func__, part);
+ return -1;
+ }
+
/* The ulong casting limits the maximum disk size to 2 TB */
info->start = (ulong) le64_to_int(gpt_pte[part - 1].starting_lba);
/* The ending LBA is inclusive, to calculate size, add 1 to it */
@@ -183,6 +212,9 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
sprintf((char *)info->name, "%s",
print_efiname(&gpt_pte[part - 1]));
sprintf((char *)info->type, "U-Boot");
+#ifdef CONFIG_PARTITION_UUIDS
+ uuid_string(gpt_pte[part - 1].unique_partition_guid.b, info->uuid);
+#endif
debug("%s: start 0x%lX, size 0x%lX, name %s", __func__,
info->start, info->size, info->name);
diff --git a/disk/part_mac.c b/disk/part_mac.c
index c1afc8c..cb443ac 100644
--- a/disk/part_mac.c
+++ b/disk/part_mac.c
@@ -60,23 +60,23 @@ static int part_mac_read_pdb (block_dev_desc_t *dev_desc, int part, mac_partitio
*/
int test_part_mac (block_dev_desc_t *dev_desc)
{
- mac_driver_desc_t ddesc;
- mac_partition_t mpart;
+ ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1);
+ ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1);
ulong i, n;
- if (part_mac_read_ddb (dev_desc, &ddesc)) {
+ if (part_mac_read_ddb (dev_desc, ddesc)) {
/* error reading Driver Desriptor Block, or no valid Signature */
return (-1);
}
n = 1; /* assuming at least one partition */
for (i=1; i<=n; ++i) {
- if ((dev_desc->block_read(dev_desc->dev, i, 1, (ulong *)&mpart) != 1) ||
- (mpart.signature != MAC_PARTITION_MAGIC) ) {
+ if ((dev_desc->block_read(dev_desc->dev, i, 1, (ulong *)mpart) != 1) ||
+ (mpart->signature != MAC_PARTITION_MAGIC) ) {
return (-1);
}
/* update partition count */
- n = mpart.map_count;
+ n = mpart->map_count;
}
return (0);
}
@@ -85,20 +85,20 @@ int test_part_mac (block_dev_desc_t *dev_desc)
void print_part_mac (block_dev_desc_t *dev_desc)
{
ulong i, n;
- mac_driver_desc_t ddesc;
- mac_partition_t mpart;
+ ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1);
+ ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1);
ldiv_t mb, gb;
- if (part_mac_read_ddb (dev_desc, &ddesc)) {
+ if (part_mac_read_ddb (dev_desc, ddesc)) {
/* error reading Driver Desriptor Block, or no valid Signature */
return;
}
- n = ddesc.blk_count;
+ n = ddesc->blk_count;
- mb = ldiv(n, ((1024 * 1024) / ddesc.blk_size)); /* MB */
+ mb = ldiv(n, ((1024 * 1024) / ddesc->blk_size)); /* MB */
/* round to 1 digit */
- mb.rem *= 10 * ddesc.blk_size;
+ mb.rem *= 10 * ddesc->blk_size;
mb.rem += 512 * 1024;
mb.rem /= 1024 * 1024;
@@ -112,10 +112,10 @@ void print_part_mac (block_dev_desc_t *dev_desc)
"DeviceType=0x%x, DeviceId=0x%x\n\n"
" #: type name"
" length base (size)\n",
- ddesc.blk_size,
- ddesc.blk_count,
+ ddesc->blk_size,
+ ddesc->blk_count,
mb.quot, mb.rem, gb.quot, gb.rem,
- ddesc.dev_type, ddesc.dev_id
+ ddesc->dev_type, ddesc->dev_id
);
n = 1; /* assuming at least one partition */
@@ -124,25 +124,25 @@ void print_part_mac (block_dev_desc_t *dev_desc)
char c;
printf ("%4ld: ", i);
- if (dev_desc->block_read (dev_desc->dev, i, 1, (ulong *)&mpart) != 1) {
+ if (dev_desc->block_read (dev_desc->dev, i, 1, (ulong *)mpart) != 1) {
printf ("** Can't read Partition Map on %d:%ld **\n",
dev_desc->dev, i);
return;
}
- if (mpart.signature != MAC_PARTITION_MAGIC) {
+ if (mpart->signature != MAC_PARTITION_MAGIC) {
printf ("** Bad Signature on %d:%ld - "
"expected 0x%04x, got 0x%04x\n",
- dev_desc->dev, i, MAC_PARTITION_MAGIC, mpart.signature);
+ dev_desc->dev, i, MAC_PARTITION_MAGIC, mpart->signature);
return;
}
/* update partition count */
- n = mpart.map_count;
+ n = mpart->map_count;
c = 'k';
- bytes = mpart.block_count;
- bytes /= (1024 / ddesc.blk_size); /* kB; assumes blk_size == 512 */
+ bytes = mpart->block_count;
+ bytes /= (1024 / ddesc->blk_size); /* kB; assumes blk_size == 512 */
if (bytes >= 1024) {
bytes >>= 10;
c = 'M';
@@ -153,10 +153,10 @@ void print_part_mac (block_dev_desc_t *dev_desc)
}
printf ("%20.32s %-18.32s %10u @ %-10u (%3ld%c)\n",
- mpart.type,
- mpart.name,
- mpart.block_count,
- mpart.start_block,
+ mpart->type,
+ mpart->name,
+ mpart->block_count,
+ mpart->start_block,
bytes, c
);
}
@@ -231,23 +231,23 @@ static int part_mac_read_pdb (block_dev_desc_t *dev_desc, int part, mac_partitio
int get_partition_info_mac (block_dev_desc_t *dev_desc, int part, disk_partition_t *info)
{
- mac_driver_desc_t ddesc;
- mac_partition_t mpart;
+ ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1);
+ ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1);
- if (part_mac_read_ddb (dev_desc, &ddesc)) {
+ if (part_mac_read_ddb (dev_desc, ddesc)) {
return (-1);
}
- info->blksz = ddesc.blk_size;
+ info->blksz = ddesc->blk_size;
- if (part_mac_read_pdb (dev_desc, part, &mpart)) {
+ if (part_mac_read_pdb (dev_desc, part, mpart)) {
return (-1);
}
- info->start = mpart.start_block;
- info->size = mpart.block_count;
- memcpy (info->type, mpart.type, sizeof(info->type));
- memcpy (info->name, mpart.name, sizeof(info->name));
+ info->start = mpart->start_block;
+ info->size = mpart->block_count;
+ memcpy (info->type, mpart->type, sizeof(info->type));
+ memcpy (info->name, mpart->name, sizeof(info->name));
return (0);
}