summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikhail Kshevetskiy2026-01-05 04:55:50 +0000
committerRobert Marko2026-03-05 10:03:06 +0000
commit5b6ef84eaa749b109d2397ded533eca6aa9b8560 (patch)
tree21249da3552afdd3cdcbcfa85c37ad1d8ff9c39b
parentc0d7de851c9a0c803d6e060736db52a03b27aa2d (diff)
downloadfirmware-utils-5b6ef84eaa749b109d2397ded533eca6aa9b8560.tar.gz
ptgen: allow to specify index of gpt entries to be used
This patch allows to specify the GPT entry index to use. Subsequent partitions will use sequential indexes, starting with the specified one. This will continue until a new starting index is specified. The patch ensures that the same index will never be used twice. [Explanation within example] ptgen creates gpt partitions using consecutive indexes starting from zero. For example the following command ptgen -o mmc.img -g -d 32M \ -p 2M \ # describe /dev/mmcblk0p1 (index=0) -p 4M \ # describe /dev/mmcblk0p2 (index=1) -p 25M # describe /dev/mmcblk0p3 (index=2) will create $ /sbin/fdisk mmc.img ... Device Start End Sectors Size Type mmc.img1 34 4129 4096 2M Linux filesystem <= see here mmc.img2 4130 12321 8192 4M Linux filesystem mmc.img3 12322 63521 51200 25M Linux filesystem Sometimes it's necessary to create one or more partitions whose indexes don't follow above rule. For example, we might want the partition located at the very beginning of the mmc flash to be named as /dev/mmcblk0p7. Within a patch this can be achieved by a command ptgen -o mmc.img -g -d 32M \ -i 6 -p 2M \ # describe /dev/mmcblk0p7 (index=6) -i 0 -p 4M \ # describe /dev/mmcblk0p1 (index=0) -p 20M # describe /dev/mmcblk0p2 (index=1) $ /sbin/fdisk mmc.img ... Device Start End Sectors Size Type mmc.img1 4130 12321 8192 4M Linux filesystem mmc.img2 12322 63521 51200 25M Linux filesystem mmc.img7 34 4129 4096 2M Linux filesystem <== see here So we done it. Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu> Link: https://github.com/openwrt/firmware-utils/pull/58 Signed-off-by: Robert Marko <robimarko@gmail.com>
-rw-r--r--src/ptgen.c53
1 files changed, 40 insertions, 13 deletions
diff --git a/src/ptgen.c b/src/ptgen.c
index dd27b07..d0786e9 100644
--- a/src/ptgen.c
+++ b/src/ptgen.c
@@ -131,6 +131,7 @@ struct partinfo {
bool has_guid;
guid_t guid;
uint64_t gattr; /* GPT partition attributes */
+ unsigned part_index; /* index of GPT entry to be used */
};
/* GPT Partition table header */
@@ -170,6 +171,7 @@ int kb_align = 0;
bool ignore_null_sized_partition = false;
bool use_guid_partition_table = false;
struct partinfo parts[GPT_ENTRY_MAX];
+bool entry_used[GPT_ENTRY_MAX] = { false };
char *filename = NULL;
int gpt_split_image = false;
@@ -422,7 +424,7 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
uint64_t start, end;
uint64_t sect = GPT_SIZE + gpt_first_entry_sector;
int fd, ret = -1;
- unsigned i, pmbr = 1;
+ unsigned i, index, pmbr = 1;
char img_name[strlen(filename) + 20];
memset(pte, 0, sizeof(struct pte) * MBR_ENTRY_MAX);
@@ -452,13 +454,15 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
return ret;
}
parts[i].actual_start = start;
- gpte[i].start = cpu_to_le64(start);
+
+ index = parts[i].part_index;
+ gpte[index].start = cpu_to_le64(start);
sect = start + parts[i].size * 2;
- gpte[i].end = cpu_to_le64(sect -1);
- gpte[i].guid = guid;
- gpte[i].guid.b[sizeof(guid_t) -1] += i + 1;
- gpte[i].type = parts[i].guid;
+ gpte[index].end = cpu_to_le64(sect -1);
+ gpte[index].guid = guid;
+ gpte[index].guid.b[sizeof(guid_t) -1] += i + 1;
+ gpte[index].type = parts[i].guid;
if (parts[i].hybrid && pmbr < MBR_ENTRY_MAX) {
pte[pmbr].active = ((i + 1) == active) ? 0x80 : 0;
@@ -469,16 +473,16 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
to_chs(sect - 1, pte[1].chs_end);
pmbr++;
}
- gpte[i].attr = parts[i].gattr;
+ gpte[index].attr = parts[i].gattr;
if (parts[i].name)
- init_utf16(parts[i].name, (uint16_t *)gpte[i].name, GPT_ENTRY_NAME_SIZE / sizeof(uint16_t));
+ init_utf16(parts[i].name, (uint16_t *)gpte[index].name, GPT_ENTRY_NAME_SIZE / sizeof(uint16_t));
if ((i + 1) == (unsigned)active)
- gpte[i].attr |= GPT_ATTR_LEGACY_BOOT;
+ gpte[index].attr |= GPT_ATTR_LEGACY_BOOT;
if (parts[i].required)
- gpte[i].attr |= GPT_ATTR_PLAT_REQUIRED;
+ gpte[index].attr |= GPT_ATTR_PLAT_REQUIRED;
if (verbose)
fprintf(stderr, "Partition %d: start=%" PRIu64 ", end=%" PRIu64 ", size=%" PRIu64 "\n",
@@ -489,7 +493,8 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
printf("%" PRIu64 "\n", (sect - start) * DISK_SECTOR_SIZE);
}
- if (parts[0].actual_start > gpt_first_entry_sector + GPT_SIZE) {
+ if (parts[0].actual_start > gpt_first_entry_sector + GPT_SIZE &&
+ !entry_used[GPT_ENTRY_MAX - 1]) {
gpte[GPT_ENTRY_MAX - 1].start = cpu_to_le64(gpt_first_entry_sector + GPT_SIZE);
gpte[GPT_ENTRY_MAX - 1].end = cpu_to_le64(parts[0].actual_start - 1);
gpte[GPT_ENTRY_MAX - 1].type = GUID_PARTITION_BIOS_BOOT;
@@ -620,7 +625,7 @@ static void usage(char *prog)
{
fprintf(stderr, "Usage: %s [-v] [-n] [-b] [-g] -h <heads> -s <sectors> -o <outputfile>\n"
" [-a <part number>] [-l <align kB>] [-G <guid>]\n"
- " [-e <gpt_entry_offset>] [-d <gpt_disk_size>]\n"
+ " [-e <gpt_entry_offset>] [-i <gpt_entry_index>] [-d <gpt_disk_size>]\n"
" [[-t <type> | -T <GPT part type>] [-r] [-N <name>] -p <size>[@<start>]...] \n", prog);
exit(EXIT_FAILURE);
@@ -653,6 +658,7 @@ int main (int argc, char **argv)
char *p;
int ch;
int part = 0;
+ unsigned part_index = 0;
char *name = NULL;
unsigned short int hybrid = 0, required = 0;
uint64_t total_sectors;
@@ -660,7 +666,7 @@ int main (int argc, char **argv)
guid_t guid = GUID_INIT( signature, 0x2211, 0x4433, \
0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0x00);
- while ((ch = getopt(argc, argv, "h:s:p:a:t:T:o:vnbHN:gl:rS:G:e:d:")) != -1) {
+ while ((ch = getopt(argc, argv, "h:s:p:a:t:T:o:vnbHN:gl:rS:G:e:d:i:")) != -1) {
switch (ch) {
case 'o':
filename = optarg;
@@ -719,6 +725,11 @@ int main (int argc, char **argv)
fputs("Too many partitions\n", stderr);
exit(EXIT_FAILURE);
}
+ if (entry_used[part_index]) {
+ fprintf(stderr, "Partition entry with index %d already defined\n", part_index);
+ exit(EXIT_FAILURE);
+ }
+
p = strchr(optarg, '@');
if (p) {
*(p++) = 0;
@@ -731,6 +742,7 @@ int main (int argc, char **argv)
parts[part].required = required;
parts[part].name = name;
parts[part].hybrid = hybrid;
+ parts[part].part_index = part_index;
fprintf(stderr, "part %lld %lld\n", parts[part].start, parts[part].size);
parts[part++].type = type;
/*
@@ -740,6 +752,13 @@ int main (int argc, char **argv)
name = NULL;
required = 0;
hybrid = 0;
+
+ /* mark index as used, switch to next index */
+ entry_used[part_index++] = true;
+ if (part_index > GPT_ENTRY_MAX - 1 ||
+ (!use_guid_partition_table && part_index > 3))
+ part_index = 0;
+
break;
case 'N':
name = optarg;
@@ -747,6 +766,14 @@ int main (int argc, char **argv)
case 'r':
required = 1;
break;
+ case 'i':
+ part_index = (int)strtoul(optarg, NULL, 0);
+ if (part_index > GPT_ENTRY_MAX - 1 ||
+ (!use_guid_partition_table && part_index > 3)) {
+ fprintf(stderr, "Too big GPT/MBR entry index %d\n", part_index);
+ exit(EXIT_FAILURE);
+ }
+ break;
case 't':
type = (char)strtoul(optarg, NULL, 16);
break;