libfdisk: Include table-length in first-lba checks

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.
This commit is contained in:
Samuel Dionne-Riel 2021-04-17 02:17:53 -04:00
parent 1c75a85101
commit fb64d93288
1 changed files with 23 additions and 13 deletions

View File

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