From 3f2d14829150c5a735271fcfd27dea0e898f6fb0 Mon Sep 17 00:00:00 2001 From: Mikhail Kshevetskiy Date: Mon, 30 Dec 2024 02:58:15 +0300 Subject: [PATCH] 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 --- src/ptgen.c | 30 +++++++++++++++++++++++------- 1 file 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 -s -o \n" " [-a ] [-l ] [-G ]\n" + " [-e ]\n" " [[-t | -T ] [-r] [-N ] -p [@]...] \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; -- 2.30.2