@@ -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;
169170int kb_align = 0 ;
170171bool ignore_null_sized_partition = false;
171172bool 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+ */
172179struct partinfo parts [GPT_ENTRY_MAX ];
173180char * 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 ;
399466fail :
400467 close (fd );
@@ -568,7 +635,7 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
568635
569636static 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