Skip to content

Commit 211dcdc

Browse files
author
Chanj Wons
committed
firmware-utils/ptgen: add support for EBR (MBR extended partition)
Adding -e option to enable MBR extended partition automatically. MBR with EBR is important in some cases. For example Raspberry4B SD card A/B boot solution needs extended partition to enable 5 available partitions at least. Signed-off-by: Chanj Wons <wangchangqi@kylinos.cn>
1 parent bd7fcc7 commit 211dcdc

File tree

1 file changed

+90
-7
lines changed

1 file changed

+90
-7
lines changed

src/ptgen.c

Lines changed: 90 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ typedef struct {
107107
#define MBR_DISK_SIGNATURE_OFFSET 440
108108
#define MBR_PARTITION_ENTRY_OFFSET 446
109109
#define MBR_BOOT_SIGNATURE_OFFSET 510
110+
#define MBR_MSDOS_SYSTYPE_EXTENDED 5
110111

111112
#define DISK_SECTOR_SIZE 512
112113

@@ -169,6 +170,12 @@ int sectors = -1;
169170
int kb_align = 0;
170171
bool ignore_null_sized_partition = false;
171172
bool use_guid_partition_table = false;
173+
bool use_mbr_extended_partition = false;
174+
/**
175+
* If only MBR: 4 primary partitions is enough, or use 3 primary partitions and 1 extended partition.
176+
* If MBR with EBR: At least 5 are needed, 3 primary, 1 extended, 1 logic.
177+
* If GPT: At most 128 can be used under Windows.
178+
*/
172179
struct partinfo parts[GPT_ENTRY_MAX];
173180
char *filename = NULL;
174181

@@ -324,7 +331,7 @@ static inline void init_utf16(char *str, uint16_t *buf, unsigned bufsize)
324331
}
325332

326333
/* check the partition sizes and write the partition table */
327-
static int gen_ptable(uint32_t signature, int nr)
334+
static int gen_ptable(uint32_t signature, int nr, int realnr)
328335
{
329336
struct pte pte[MBR_ENTRY_MAX];
330337
unsigned long start, len, sect = 0;
@@ -364,7 +371,7 @@ static int gen_ptable(uint32_t signature, int nr)
364371
to_chs(start + len - 1, pte[i].chs_end);
365372

366373
if (verbose)
367-
fprintf(stderr, "Partition %d: start=%ld, end=%ld, size=%ld\n",
374+
fprintf(stderr, "MBR Partition %d: start=%ld, end=%ld, size=%ld\n",
368375
i,
369376
(long)start * DISK_SECTOR_SIZE,
370377
(long)(start + len) * DISK_SECTOR_SIZE,
@@ -395,6 +402,66 @@ static int gen_ptable(uint32_t signature, int nr)
395402
goto fail;
396403
}
397404

405+
if (use_mbr_extended_partition) {
406+
int _start = 0;
407+
int offset = pte[3].start * 512;
408+
409+
for (i = nr; i < realnr; i++) {
410+
unsigned long sect = 0;
411+
int start = sectors, len;
412+
struct pte ebrpte[2];
413+
memset(ebrpte, 0, sizeof(ebrpte));
414+
415+
if (!parts[i].size) {
416+
if (ignore_null_sized_partition)
417+
continue;
418+
fprintf(stderr, "Invalid size in partition %d!\n", i);
419+
return -1;
420+
}
421+
422+
ebrpte[0].active = 0;
423+
ebrpte[0].type = parts[i].type;
424+
425+
if (kb_align != 0)
426+
start = round_to_kb(start);
427+
ebrpte[0].start = cpu_to_le32(start);
428+
429+
sect = start + parts[i].size * 2;
430+
if (kb_align == 0)
431+
sect = round_to_cyl(sect);
432+
ebrpte[0].length = cpu_to_le32(len = sect - start);
433+
434+
to_chs(start, ebrpte[0].chs_start);
435+
to_chs(start + len - 1, ebrpte[0].chs_end);
436+
437+
/* ebrpte[1] -> point next EBR */
438+
if (realnr - i > 1) {
439+
_start += sect;
440+
ebrpte[1].type = MBR_MSDOS_SYSTYPE_EXTENDED;
441+
ebrpte[1].start = cpu_to_le32(_start);
442+
}
443+
444+
if (verbose)
445+
fprintf(stderr, "EBR Partition %d: start=%ld, end=%ld, size=%ld\n", i - nr, (long)start * 512, ((long)start + (long)len) * 512, (long)len * 512);
446+
printf("%ld\n", (long)start * 512);
447+
printf("%ld\n", (long)len * 512);
448+
449+
lseek(fd, offset + 446, SEEK_SET);
450+
if (write(fd, ebrpte, sizeof(struct pte) * 2) != sizeof(struct pte) * 2) {
451+
fprintf(stderr, "write failed.\n");
452+
goto fail;
453+
}
454+
455+
lseek(fd, offset + 510, SEEK_SET);
456+
if (write(fd, "\x55\xaa", 2) != 2) {
457+
fprintf(stderr, "write failed.\n");
458+
goto fail;
459+
}
460+
461+
offset += sect * 512;
462+
}
463+
}
464+
398465
ret = 0;
399466
fail:
400467
close(fd);
@@ -568,7 +635,7 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
568635

569636
static void usage(char *prog)
570637
{
571-
fprintf(stderr, "Usage: %s [-v] [-n] [-g] -h <heads> -s <sectors> -o <outputfile>\n"
638+
fprintf(stderr, "Usage: %s [-v] [-n] [-g] [-e] -h <heads> -s <sectors> -o <outputfile>\n"
572639
" [-a <part number>] [-l <align kB>] [-G <guid>]\n"
573640
" [[-t <type> | -T <GPT part type>] [-r] [-N <name>] -p <size>[@<start>]...] \n", prog);
574641
exit(EXIT_FAILURE);
@@ -607,7 +674,7 @@ int main (int argc, char **argv)
607674
guid_t guid = GUID_INIT( signature, 0x2211, 0x4433, \
608675
0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0x00);
609676

610-
while ((ch = getopt(argc, argv, "h:s:p:a:t:T:o:vnHN:gl:rS:G:")) != -1) {
677+
while ((ch = getopt(argc, argv, "h:s:p:a:t:T:o:evnHN:gl:rS:G:")) != -1) {
611678
switch (ch) {
612679
case 'o':
613680
filename = optarg;
@@ -624,17 +691,26 @@ int main (int argc, char **argv)
624691
case 'H':
625692
hybrid = 1;
626693
break;
694+
case 'e':
695+
use_mbr_extended_partition = 1;
696+
break;
627697
case 'h':
628698
heads = (int)strtoul(optarg, NULL, 0);
629699
break;
630700
case 's':
631701
sectors = (int)strtoul(optarg, NULL, 0);
632702
break;
633703
case 'p':
634-
if (part > GPT_ENTRY_MAX - 1 || (!use_guid_partition_table && part > 3)) {
635-
fputs("Too many partitions\n", stderr);
704+
if (part > GPT_ENTRY_MAX - 1 || ((!use_guid_partition_table && !use_mbr_extended_partition) && part > 3)) {
705+
fputs("Too many partitions, please add the -e parameter to automatically enable MBR extended partition\n", stderr);
636706
exit(EXIT_FAILURE);
637707
}
708+
if (part == 3 && use_mbr_extended_partition) {
709+
parts[part++].type = MBR_MSDOS_SYSTYPE_EXTENDED;
710+
parts[part].size = to_kbytes(optarg);
711+
parts[part++].type = type;
712+
break;
713+
}
638714
p = strchr(optarg, '@');
639715
if (p) {
640716
*(p++) = 0;
@@ -709,5 +785,12 @@ int main (int argc, char **argv)
709785
return gen_gptable(signature, guid, part) ? EXIT_FAILURE : EXIT_SUCCESS;
710786
}
711787

712-
return gen_ptable(signature, part) ? EXIT_FAILURE : EXIT_SUCCESS;
788+
if (part > 4) {
789+
int logic_parts_sizes = 0;
790+
for (int i = 4; i < part; i++)
791+
logic_parts_sizes += kb_align / 2 + parts[i].size;
792+
parts[3].size = logic_parts_sizes;
793+
}
794+
795+
return gen_ptable(signature, part > 3 ? 4 : part, part) ? EXIT_FAILURE : EXIT_SUCCESS;
713796
}

0 commit comments

Comments
 (0)