test: dm_mdio: avoid out of bounds access
[oweals/u-boot.git] / disk / part.c
index 862078f3e7c8a296a1357fa112fe42a119ff2bd5..8982ef3baed129f13ed8936eecb2380a334c9b0b 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <env.h>
 #include <errno.h>
 #include <ide.h>
 #include <malloc.h>
@@ -414,11 +415,10 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str,
 #ifdef CONFIG_HAVE_BLOCK_DEVICE
        /*
         * Updates the partition table for the specified hw partition.
-        * Does not need to be done for hwpart 0 since it is default and
-        * already loaded.
+        * Always should be done, otherwise hw partition 0 will return stale
+        * data after displaying a non-zero hw partition.
         */
-       if(hwpart != 0)
-               part_init(*dev_desc);
+       part_init(*dev_desc);
 #endif
 
 cleanup:
@@ -675,6 +675,74 @@ int part_get_info_by_name(struct blk_desc *dev_desc, const char *name,
        return part_get_info_by_name_type(dev_desc, name, info, PART_TYPE_ALL);
 }
 
+/**
+ * Get partition info from device number and partition name.
+ *
+ * Parse a device number and partition name string in the form of
+ * "device_num#partition_name", for example "0#misc". If the partition
+ * is found, sets dev_desc and part_info accordingly with the information
+ * of the partition with the given partition_name.
+ *
+ * @param[in] dev_iface Device interface
+ * @param[in] dev_part_str Input string argument, like "0#misc"
+ * @param[out] dev_desc Place to store the device description pointer
+ * @param[out] part_info Place to store the partition information
+ * @return 0 on success, or a negative on error
+ */
+static int part_get_info_by_dev_and_name(const char *dev_iface,
+                                        const char *dev_part_str,
+                                        struct blk_desc **dev_desc,
+                                        disk_partition_t *part_info)
+{
+       char *ep;
+       const char *part_str;
+       int dev_num;
+
+       part_str = strchr(dev_part_str, '#');
+       if (!part_str || part_str == dev_part_str)
+               return -EINVAL;
+
+       dev_num = simple_strtoul(dev_part_str, &ep, 16);
+       if (ep != part_str) {
+               /* Not all the first part before the # was parsed. */
+               return -EINVAL;
+       }
+       part_str++;
+
+       *dev_desc = blk_get_dev(dev_iface, dev_num);
+       if (!*dev_desc) {
+               printf("Could not find %s %d\n", dev_iface, dev_num);
+               return -EINVAL;
+       }
+       if (part_get_info_by_name(*dev_desc, part_str, part_info) < 0) {
+               printf("Could not find \"%s\" partition\n", part_str);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+int part_get_info_by_dev_and_name_or_num(const char *dev_iface,
+                                        const char *dev_part_str,
+                                        struct blk_desc **dev_desc,
+                                        disk_partition_t *part_info)
+{
+       /* Split the part_name if passed as "$dev_num#part_name". */
+       if (!part_get_info_by_dev_and_name(dev_iface, dev_part_str,
+                                          dev_desc, part_info))
+               return 0;
+       /*
+        * Couldn't lookup by name, try looking up the partition description
+        * directly.
+        */
+       if (blk_get_device_part_str(dev_iface, dev_part_str,
+                                   dev_desc, part_info, 1) < 0) {
+               printf("Couldn't find partition %s %s\n",
+                      dev_iface, dev_part_str);
+               return -EINVAL;
+       }
+       return 0;
+}
+
 void part_set_generic_name(const struct blk_desc *dev_desc,
        int part_num, char *name)
 {