git: 729883c93e7f - main - mkimg: Add per-partition alignment
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 21 Oct 2026 20:48:33 UTC
The branch main has been updated by cperciva:
URL: https://cgit.FreeBSD.org/src/commit/?id=729883c93e7fd89a4b88e8b9a7ef42938a431efa
commit 729883c93e7fd89a4b88e8b9a7ef42938a431efa
Author: Colin Percival <cperciva@FreeBSD.org>
AuthorDate: 2026-10-07 21:51:26 +0000
Commit: Colin Percival <cperciva@FreeBSD.org>
CommitDate: 2026-10-21 19:42:43 +0000
mkimg: Add per-partition alignment
This adds a "%align" field to partition specifications, resulting in
the start of a partition being shifted to the next aligned position.
When both :offset and %align are used, a relative offset is treated as
a minimum value, while an unaligned absolute offset is an error.
Reviewed by: imp (earlier version)
MFC after: 1 week
Sponsored by: Amazon
Differential Revision: https://reviews.freebsd.org/D60450
---
usr.bin/mkimg/mkimg.c | 62 +++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 50 insertions(+), 12 deletions(-)
diff --git a/usr.bin/mkimg/mkimg.c b/usr.bin/mkimg/mkimg.c
index b727b43683a3..a1881b114b7f 100644
--- a/usr.bin/mkimg/mkimg.c
+++ b/usr.bin/mkimg/mkimg.c
@@ -178,13 +178,15 @@ usage(const char *why)
print_schemes(1);
fputc('\n', stderr);
fprintf(stderr, " partition specification:\n");
- fprintf(stderr, "\t<type>[/<label>]::<size>[:[+]<offset>]\t- "
- "empty partition of given size and\n\t\t\t\t\t"
- " optional relative or absolute offset\n");
- fprintf(stderr, "\t<type>[/<label>]:=<file>[:[+]offset]\t- partition "
- "content and size are\n\t\t\t\t\t"
- " determined by the named file and\n"
- "\t\t\t\t\t optional relative or absolute offset\n");
+ fprintf(stderr, "\t<type>[/<label>]::<size>[:[+]<offset>][%%<align>]\n"
+ "\t\t\t\t\t- empty partition of given size and\n"
+ "\t\t\t\t\t optional relative or absolute offset\n"
+ "\t\t\t\t\t and alignment\n");
+ fprintf(stderr, "\t<type>[/<label>]:=<file>[:[+]<offset>][%%<align>]\n"
+ "\t\t\t\t\t- partition content and size are\n"
+ "\t\t\t\t\t determined by the named file and\n"
+ "\t\t\t\t\t optional relative or absolute offset\n"
+ "\t\t\t\t\t and alignment\n");
fprintf(stderr, "\t<type>[/<label>]:-<cmd>\t\t- partition content and size "
"are taken\n\t\t\t\t\t from the output of the command to run\n");
fprintf(stderr, "\t-\t\t\t\t- unused partition entry\n");
@@ -448,9 +450,9 @@ mkimg(void)
struct part *part;
struct stat sb;
char *p;
- lba_t block, blkoffset;
- uint64_t bytesize, byteoffset;
- char *size, *offset;
+ lba_t block, blkoffset, blkalign;
+ uint64_t bytesize, byteoffset, bytealign;
+ char *size, *offset, *align;
bool abs_offset;
int error, fd;
@@ -466,10 +468,16 @@ mkimg(void)
TAILQ_FOREACH(part, &partlist, link) {
byteoffset = blkoffset = 0;
abs_offset = false;
+ align = NULL;
/* Look for an offset. Set size too if we can. */
switch (part->kind) {
case PART_KIND_SIZE:
+ p = strrchr(part->contents, '%');
+ if (p != NULL) {
+ *p = '\0';
+ align = p + 1;
+ }
offset = part->contents;
size = strsep(&offset, ":");
if (expand_number(size, &bytesize) == -1)
@@ -477,6 +485,13 @@ mkimg(void)
break;
case PART_KIND_FILE:
size = part->contents;
+ if (stat(part->contents, &sb) == -1) {
+ p = strrchr(part->contents, '%');
+ if (p != NULL) {
+ *p = '\0';
+ align = p + 1;
+ }
+ }
if (stat(part->contents, &sb) == 0) {
if (S_ISDIR(sb.st_mode)) {
errc(EX_IOERR, EISDIR, "partition %d",
@@ -498,6 +513,18 @@ mkimg(void)
break;
}
+ if (align != NULL) {
+ if (expand_number(align, &bytealign) == -1)
+ err(EX_DATAERR, "partition %d",
+ part->index + 1);
+ if ((bytealign == 0) || (bytealign % secsz != 0))
+ errx(EX_DATAERR, "partition %d: "
+ "invalid alignment", part->index + 1);
+ blkalign = bytealign / secsz;
+ } else {
+ blkalign = 1;
+ }
+
if (offset != NULL) {
if (*offset != '+')
abs_offset = true;
@@ -509,12 +536,17 @@ mkimg(void)
/* Work out exactly where the partition starts. */
blkoffset = (byteoffset + secsz - 1) / secsz;
- if (abs_offset)
+ if (abs_offset) {
block = scheme_metadata(SCHEME_META_PART_ABSOLUTE,
blkoffset);
- else
+ if (block % blkalign)
+ errx(EX_DATAERR, "partition %d: absolute "
+ "offset incompatible with alignment",
+ part->index + 1);
+ } else
block = scheme_metadata(SCHEME_META_PART_BEFORE,
block + blkoffset);
+ block = ((block + blkalign - 1) / blkalign) * blkalign;
part->block = block;
if (verbose)
@@ -559,6 +591,12 @@ mkimg(void)
(long long)byteoffset,
(long long)blkoffset);
}
+ if (blkalign > 1) {
+ fprintf(stderr,
+ " alignment %llu bytes (%llu blocks)\n",
+ (long long)bytealign,
+ (long long)blkalign);
+ }
}
block = scheme_metadata(SCHEME_META_PART_AFTER,
part->block + part->size);