summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikhail Kshevetskiy2024-12-29 23:58:15 +0000
committerDaniel Golle2025-09-23 22:15:33 +0000
commit3f2d14829150c5a735271fcfd27dea0e898f6fb0 (patch)
tree31411550e857af2437cddf4b74264cc408974a10
parentf1f98b0b8456e89f6c959d8f028c5204da82365e (diff)
downloadfirmware-utils-3f2d14829150c5a735271fcfd27dea0e898f6fb0.tar.gz
ptgen: allow non-default placement of gpt entry table
Usually, the primary GPT entries places in the sector 2 (next sector after the primary GPT header). The boot ROM of some SoCs (like Airoha AN7581) on the other hand reads the bootloader code from only one fixed offset which overlaps with the normal position of the primary GPT entries. This patch adds a parameter to ptgen to customise the position of the primary GPT entries. Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
-rw-r--r--src/ptgen.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/src/ptgen.c b/src/ptgen.c
index 37eeac0..ed9efa3 100644
--- a/src/ptgen.c
+++ b/src/ptgen.c
@@ -172,6 +172,7 @@ bool use_guid_partition_table = false;
struct partinfo parts[GPT_ENTRY_MAX];
char *filename = NULL;
+uint64_t gpt_first_entry_sector = GPT_FIRST_ENTRY_SECTOR;
/*
* parse the size argument, which is either
@@ -408,15 +409,15 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
.revision = cpu_to_le32(GPT_REVISION),
.size = cpu_to_le32(GPT_HEADER_SIZE),
.self = cpu_to_le64(GPT_HEADER_SECTOR),
- .first_usable = cpu_to_le64(GPT_FIRST_ENTRY_SECTOR + GPT_ENTRY_SIZE * GPT_ENTRY_MAX / DISK_SECTOR_SIZE),
- .first_entry = cpu_to_le64(GPT_FIRST_ENTRY_SECTOR),
+ .first_usable = cpu_to_le64(gpt_first_entry_sector + GPT_SIZE),
+ .first_entry = cpu_to_le64(gpt_first_entry_sector),
.disk_guid = guid,
.entry_num = cpu_to_le32(GPT_ENTRY_MAX),
.entry_size = cpu_to_le32(GPT_ENTRY_SIZE),
};
struct gpte gpte[GPT_ENTRY_MAX];
uint64_t start, end;
- uint64_t sect = GPT_SIZE + GPT_FIRST_ENTRY_SECTOR;
+ uint64_t sect = GPT_SIZE + gpt_first_entry_sector;
int fd, ret = -1;
unsigned i, pmbr = 1;
@@ -479,8 +480,8 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
}
if ((parts[0].start != 0) &&
- (parts[0].actual_start > GPT_FIRST_ENTRY_SECTOR + GPT_SIZE)) {
- gpte[GPT_ENTRY_MAX - 1].start = cpu_to_le64(GPT_FIRST_ENTRY_SECTOR + GPT_SIZE);
+ (parts[0].actual_start > gpt_first_entry_sector + GPT_SIZE)) {
+ 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;
gpte[GPT_ENTRY_MAX - 1].guid = guid;
@@ -500,6 +501,10 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
gpth.entry_crc32 = cpu_to_le32(gpt_crc32(gpte, GPT_ENTRY_SIZE * GPT_ENTRY_MAX));
gpth.crc32 = cpu_to_le32(gpt_crc32((char *)&gpth, GPT_HEADER_SIZE));
+ if (verbose)
+ fprintf(stderr, "PartitionEntryLBA=%" PRIu64 ", FirstUsableLBA=%" PRIu64 ", LastUsableLBA=%" PRIu64 "\n",
+ gpt_first_entry_sector, gpt_first_entry_sector + GPT_SIZE, end - GPT_SIZE - 1);
+
if ((fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
fprintf(stderr, "Can't open output file '%s'\n",filename);
return ret;
@@ -528,7 +533,7 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
goto fail;
}
- lseek(fd, GPT_FIRST_ENTRY_SECTOR * DISK_SECTOR_SIZE, SEEK_SET);
+ lseek(fd, gpt_first_entry_sector * DISK_SECTOR_SIZE, SEEK_SET);
if (write(fd, &gpte, GPT_ENTRY_SIZE * GPT_ENTRY_MAX) != GPT_ENTRY_SIZE * GPT_ENTRY_MAX) {
fputs("write failed.\n", stderr);
goto fail;
@@ -569,7 +574,9 @@ static void usage(char *prog)
{
fprintf(stderr, "Usage: %s [-v] [-n] [-g] -h <heads> -s <sectors> -o <outputfile>\n"
" [-a <part number>] [-l <align kB>] [-G <guid>]\n"
+ " [-e <gpt_entry_offset>]\n"
" [[-t <type> | -T <GPT part type>] [-r] [-N <name>] -p <size>[@<start>]...] \n", prog);
+
exit(EXIT_FAILURE);
}
@@ -606,7 +613,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:vnHN:gl:rS:G:")) != -1) {
+ while ((ch = getopt(argc, argv, "h:s:p:a:t:T:o:vnHN:gl:rS:G:e:")) != -1) {
switch (ch) {
case 'o':
filename = optarg;
@@ -623,6 +630,15 @@ int main (int argc, char **argv)
case 'H':
hybrid = 1;
break;
+ case 'e':
+ /* based on DISK_SECTOR_SIZE = 512 */
+ gpt_first_entry_sector = 2 * to_kbytes(optarg);
+ if (gpt_first_entry_sector < GPT_FIRST_ENTRY_SECTOR) {
+ fprintf(stderr, "GPT First Entry offset must not be smaller than %d KBytes\n",
+ GPT_FIRST_ENTRY_SECTOR / 2);
+ exit(EXIT_FAILURE);
+ }
+ break;
case 'h':
heads = (int)strtoul(optarg, NULL, 0);
break;