]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: Include table-length in first-lba checks
authorSamuel Dionne-Riel <samuel@dionne-riel.com>
Sat, 17 Apr 2021 06:17:53 +0000 (02:17 -0400)
committerSamuel Dionne-Riel <samuel@dionne-riel.com>
Sat, 17 Apr 2021 20:15:19 +0000 (16:15 -0400)
Otherwise, sfdisk would error out on its own dump, as first-lba would be
earlier than "plausible" assuming the default table size.

This is because it did not look for `table-length` when using an sfdisk
script. This means that using `--dump` on a valid image, could not be
unserialized back into a valid image.

This is helpful in exotic situations, where a partition has to be
created earlier than the conventional "first-lba" (2048). For example,
on Allwinner A64 boards, where a firmware is stored at LBA16. With this
it is possible to ask for `first-lba` at or earlier than 16, by reducing
the number of entries to e.g. 48.

libfdisk/src/gpt.c

index 6b07d9841eebad68932f0845daff3d476ae3d9ba..1a086a61d8fbb891758895a1f6beb2027f812fb1 100644 (file)
@@ -747,7 +747,7 @@ static int count_first_last_lba(struct fdisk_context *cxt,
 {
        int rc = 0;
        uint64_t flba = 0, llba = 0;
-       uint32_t nents;
+       uint64_t nents = GPT_NPARTITIONS;
 
        assert(cxt);
        assert(first);
@@ -755,18 +755,28 @@ static int count_first_last_lba(struct fdisk_context *cxt,
 
        *first = *last = 0;
 
-       /* The default is GPT_NPARTITIONS, if the device is not large enough
-        * than reduce this number of partitions and try to recalculate it
-        * again, until we get something useful or return error.
-        */
-       for (nents = GPT_NPARTITIONS; nents > 0; nents--) {
-               rc = gpt_calculate_last_lba(NULL, nents, &llba, cxt);
-               if (rc == 0)
-                       rc = gpt_calculate_first_lba(NULL, nents, &flba, cxt);
-               if (llba < flba)
-                       rc = -ENOSPC;
-               else if (rc == 0)
-                       break;
+       /* Get the table length from the script, if given */
+       if (cxt->script) {
+               rc = get_script_u64(cxt, &nents, "table-length");
+               if (rc < 0)
+                       return rc;
+       }
+
+       /* The table length was not changed by the script, compute it. */
+       if (flba == 0) {
+               /* If the device is not large enough reduce this number of
+                * partitions and try to recalculate it again, until we get
+                * something useful or return error.
+                */
+               for (; nents > 0; nents--) {
+                       rc = gpt_calculate_last_lba(NULL, nents, &llba, cxt);
+                       if (rc == 0)
+                               rc = gpt_calculate_first_lba(NULL, nents, &flba, cxt);
+                       if (llba < flba)
+                               rc = -ENOSPC;
+                       else if (rc == 0)
+                               break;
+               }
        }
 
        if (rc)