firmware-utils/ptgen: add support for hybrid MBR
Adding -H option copies partition to MBR after pmbr entry. Max 3 partitions can be copied to MBR. Hybrid MBR is needed only in special cases. For example mt7622 SD card boot needs MBR entry with boot flag enabled. Signed-off-by: Oskari Lemmela <oskari@lemmela.net>
This commit is contained in:
		
				
					committed by
					
						
						Daniel Golle
					
				
			
			
				
	
			
			
			
						parent
						
							4a078bd135
						
					
				
				
					commit
					460dd2fe28
				
			@@ -123,6 +123,7 @@ struct partinfo {
 | 
				
			|||||||
	unsigned long start;
 | 
						unsigned long start;
 | 
				
			||||||
	unsigned long size;
 | 
						unsigned long size;
 | 
				
			||||||
	int type;
 | 
						int type;
 | 
				
			||||||
 | 
						int hybrid;
 | 
				
			||||||
	char *name;
 | 
						char *name;
 | 
				
			||||||
	short int required;
 | 
						short int required;
 | 
				
			||||||
	guid_t guid;
 | 
						guid_t guid;
 | 
				
			||||||
@@ -369,7 +370,7 @@ fail:
 | 
				
			|||||||
/* check the partition sizes and write the guid partition table */
 | 
					/* check the partition sizes and write the guid partition table */
 | 
				
			||||||
static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
 | 
					static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pte pte;
 | 
						struct pte pte[MBR_ENTRY_MAX];
 | 
				
			||||||
	struct gpth gpth = {
 | 
						struct gpth gpth = {
 | 
				
			||||||
		.signature = cpu_to_le64(GPT_SIGNATURE),
 | 
							.signature = cpu_to_le64(GPT_SIGNATURE),
 | 
				
			||||||
		.revision = cpu_to_le32(GPT_REVISION),
 | 
							.revision = cpu_to_le32(GPT_REVISION),
 | 
				
			||||||
@@ -384,8 +385,9 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
 | 
				
			|||||||
	struct gpte  gpte[GPT_ENTRY_MAX];
 | 
						struct gpte  gpte[GPT_ENTRY_MAX];
 | 
				
			||||||
	uint64_t start, end, sect = 0;
 | 
						uint64_t start, end, sect = 0;
 | 
				
			||||||
	int fd, ret = -1;
 | 
						int fd, ret = -1;
 | 
				
			||||||
	unsigned i;
 | 
						unsigned i, pmbr = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(pte, 0, sizeof(struct pte) * MBR_ENTRY_MAX);
 | 
				
			||||||
	memset(gpte, 0, GPT_ENTRY_SIZE * GPT_ENTRY_MAX);
 | 
						memset(gpte, 0, GPT_ENTRY_SIZE * GPT_ENTRY_MAX);
 | 
				
			||||||
	for (i = 0; i < nr; i++) {
 | 
						for (i = 0; i < nr; i++) {
 | 
				
			||||||
		if (!parts[i].size) {
 | 
							if (!parts[i].size) {
 | 
				
			||||||
@@ -415,6 +417,16 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
 | 
				
			|||||||
		gpte[i].guid.b[sizeof(guid_t) -1] += i + 1;
 | 
							gpte[i].guid.b[sizeof(guid_t) -1] += i + 1;
 | 
				
			||||||
		gpte[i].type = parts[i].guid;
 | 
							gpte[i].type = parts[i].guid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (parts[i].hybrid && pmbr < MBR_ENTRY_MAX) {
 | 
				
			||||||
 | 
								pte[pmbr].active = ((i + 1) == active) ? 0x80 : 0;
 | 
				
			||||||
 | 
								pte[pmbr].type = parts[i].type;
 | 
				
			||||||
 | 
								pte[pmbr].start = cpu_to_le32(start);
 | 
				
			||||||
 | 
								pte[pmbr].length = cpu_to_le32(sect - start);
 | 
				
			||||||
 | 
								to_chs(start, pte[1].chs_start);
 | 
				
			||||||
 | 
								to_chs(sect - 1, pte[1].chs_end);
 | 
				
			||||||
 | 
								pmbr++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (parts[i].name)
 | 
							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[i].name, GPT_ENTRY_NAME_SIZE / sizeof(uint16_t));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -441,11 +453,11 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	end = sect + sectors - 1;
 | 
						end = sect + sectors - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pte.type = 0xEE;
 | 
						pte[0].type = 0xEE;
 | 
				
			||||||
	pte.start = cpu_to_le32(GPT_HEADER_SECTOR);
 | 
						pte[0].start = cpu_to_le32(GPT_HEADER_SECTOR);
 | 
				
			||||||
	pte.length = cpu_to_le32(end);
 | 
						pte[0].length = cpu_to_le32(end - GPT_HEADER_SECTOR);
 | 
				
			||||||
	to_chs(GPT_HEADER_SECTOR, pte.chs_start);
 | 
						to_chs(GPT_HEADER_SECTOR, pte[0].chs_start);
 | 
				
			||||||
	to_chs(end, pte.chs_end);
 | 
						to_chs(end, pte[0].chs_end);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gpth.last_usable = cpu_to_le64(end - GPT_ENTRY_SIZE * GPT_ENTRY_MAX / DISK_SECTOR_SIZE - 1);
 | 
						gpth.last_usable = cpu_to_le64(end - GPT_ENTRY_SIZE * GPT_ENTRY_MAX / DISK_SECTOR_SIZE - 1);
 | 
				
			||||||
	gpth.alternate = cpu_to_le64(end);
 | 
						gpth.alternate = cpu_to_le64(end);
 | 
				
			||||||
@@ -464,7 +476,7 @@ static int gen_gptable(uint32_t signature, guid_t guid, unsigned nr)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lseek(fd, MBR_PARTITION_ENTRY_OFFSET, SEEK_SET);
 | 
						lseek(fd, MBR_PARTITION_ENTRY_OFFSET, SEEK_SET);
 | 
				
			||||||
	if (write(fd, &pte, sizeof(struct pte)) != sizeof(struct pte)) {
 | 
						if (write(fd, pte, sizeof(struct pte) * MBR_ENTRY_MAX) != sizeof(struct pte) * MBR_ENTRY_MAX) {
 | 
				
			||||||
		fputs("write failed.\n", stderr);
 | 
							fputs("write failed.\n", stderr);
 | 
				
			||||||
		goto fail;
 | 
							goto fail;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -551,13 +563,13 @@ int main (int argc, char **argv)
 | 
				
			|||||||
	int ch;
 | 
						int ch;
 | 
				
			||||||
	int part = 0;
 | 
						int part = 0;
 | 
				
			||||||
	char *name = NULL;
 | 
						char *name = NULL;
 | 
				
			||||||
	unsigned short int required = 0;
 | 
						unsigned short int hybrid = 0, required = 0;
 | 
				
			||||||
	uint32_t signature = 0x5452574F; /* 'OWRT' */
 | 
						uint32_t signature = 0x5452574F; /* 'OWRT' */
 | 
				
			||||||
	guid_t guid = GUID_INIT( signature, 0x2211, 0x4433, \
 | 
						guid_t guid = GUID_INIT( signature, 0x2211, 0x4433, \
 | 
				
			||||||
			0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0x00);
 | 
								0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0x00);
 | 
				
			||||||
	guid_t part_guid = GUID_PARTITION_BASIC_DATA;
 | 
						guid_t part_guid = GUID_PARTITION_BASIC_DATA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((ch = getopt(argc, argv, "h:s:p:a:t:o:vnN:gl:rS:G:")) != -1) {
 | 
						while ((ch = getopt(argc, argv, "h:s:p:a:t:o:vnHN:gl:rS:G:")) != -1) {
 | 
				
			||||||
		switch (ch) {
 | 
							switch (ch) {
 | 
				
			||||||
		case 'o':
 | 
							case 'o':
 | 
				
			||||||
			filename = optarg;
 | 
								filename = optarg;
 | 
				
			||||||
@@ -571,6 +583,9 @@ int main (int argc, char **argv)
 | 
				
			|||||||
		case 'g':
 | 
							case 'g':
 | 
				
			||||||
			use_guid_partition_table = 1;
 | 
								use_guid_partition_table = 1;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case 'H':
 | 
				
			||||||
 | 
								hybrid = 1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case 'h':
 | 
							case 'h':
 | 
				
			||||||
			heads = (int)strtoul(optarg, NULL, 0);
 | 
								heads = (int)strtoul(optarg, NULL, 0);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
@@ -591,15 +606,17 @@ int main (int argc, char **argv)
 | 
				
			|||||||
			parts[part].size = to_kbytes(optarg);
 | 
								parts[part].size = to_kbytes(optarg);
 | 
				
			||||||
			parts[part].required = required;
 | 
								parts[part].required = required;
 | 
				
			||||||
			parts[part].name = name;
 | 
								parts[part].name = name;
 | 
				
			||||||
 | 
								parts[part].hybrid = hybrid;
 | 
				
			||||||
			parts[part].guid = part_guid;
 | 
								parts[part].guid = part_guid;
 | 
				
			||||||
			fprintf(stderr, "part %ld %ld\n", parts[part].start, parts[part].size);
 | 
								fprintf(stderr, "part %ld %ld\n", parts[part].start, parts[part].size);
 | 
				
			||||||
			parts[part++].type = type;
 | 
								parts[part++].type = type;
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * reset 'name' and 'required'
 | 
								 * reset 'name','required' and 'hybrid'
 | 
				
			||||||
			 * 'type' is deliberately inherited from the previous delcaration
 | 
								 * 'type' is deliberately inherited from the previous delcaration
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			name = NULL;
 | 
								name = NULL;
 | 
				
			||||||
			required = 0;
 | 
								required = 0;
 | 
				
			||||||
 | 
								hybrid = 0;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case 'N':
 | 
							case 'N':
 | 
				
			||||||
			name = optarg;
 | 
								name = optarg;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user