GPT: read partition table from device into a data structure
Make the partition table available for modification by reading it from the user-specified device into a linked list. Provide an accessor function for command-line testing. Signed-off-by: Alison Chaiken <alison@peloton-tech.com> [trini: Make this depend on CMD_GPT_RENAME, as it is the user of this code] Signed-off-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
		
							parent
							
								
									73d6d18b71
								
							
						
					
					
						commit
						09a49930e4
					
				
							
								
								
									
										125
									
								
								cmd/gpt.c
								
								
								
								
							
							
						
						
									
										125
									
								
								cmd/gpt.c
								
								
								
								
							|  | @ -19,6 +19,9 @@ | ||||||
| #include <linux/ctype.h> | #include <linux/ctype.h> | ||||||
| #include <div64.h> | #include <div64.h> | ||||||
| #include <memalign.h> | #include <memalign.h> | ||||||
|  | #include <linux/compat.h> | ||||||
|  | 
 | ||||||
|  | static LIST_HEAD(disk_partitions); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * extract_env(): Expand env name from string format '&{env_name}' |  * extract_env(): Expand env name from string format '&{env_name}' | ||||||
|  | @ -151,6 +154,122 @@ static bool found_key(const char *str, const char *key) | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_CMD_GPT_RENAME | ||||||
|  | static void del_gpt_info(void) | ||||||
|  | { | ||||||
|  | 	struct list_head *pos = &disk_partitions; | ||||||
|  | 	struct disk_part *curr; | ||||||
|  | 	while (!list_empty(pos)) { | ||||||
|  | 		curr = list_entry(pos->next, struct disk_part, list); | ||||||
|  | 		list_del(pos->next); | ||||||
|  | 		free(curr); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct disk_part *allocate_disk_part(disk_partition_t *info, int partnum) | ||||||
|  | { | ||||||
|  | 	struct disk_part *newpart; | ||||||
|  | 	newpart = malloc(sizeof(*newpart)); | ||||||
|  | 	if (!newpart) | ||||||
|  | 		return ERR_PTR(-ENOMEM); | ||||||
|  | 	memset(newpart, '\0', sizeof(newpart)); | ||||||
|  | 
 | ||||||
|  | 	newpart->gpt_part_info.start = info->start; | ||||||
|  | 	newpart->gpt_part_info.size = info->size; | ||||||
|  | 	newpart->gpt_part_info.blksz = info->blksz; | ||||||
|  | 	strncpy((char *)newpart->gpt_part_info.name, (const char *)info->name, | ||||||
|  | 		PART_NAME_LEN); | ||||||
|  | 	newpart->gpt_part_info.name[PART_NAME_LEN - 1] = '\0'; | ||||||
|  | 	strncpy((char *)newpart->gpt_part_info.type, (const char *)info->type, | ||||||
|  | 		PART_TYPE_LEN); | ||||||
|  | 	newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0'; | ||||||
|  | 	newpart->gpt_part_info.bootable = info->bootable; | ||||||
|  | #ifdef CONFIG_PARTITION_UUIDS | ||||||
|  | 	strncpy(newpart->gpt_part_info.uuid, (const char *)info->uuid, | ||||||
|  | 		UUID_STR_LEN); | ||||||
|  | 	/* UUID_STR_LEN is correct, as uuid[]'s length is UUID_STR_LEN+1 chars */ | ||||||
|  | 	newpart->gpt_part_info.uuid[UUID_STR_LEN] = '\0'; | ||||||
|  | #endif | ||||||
|  | 	newpart->partnum = partnum; | ||||||
|  | 
 | ||||||
|  | 	return newpart; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void print_gpt_info(void) | ||||||
|  | { | ||||||
|  | 	struct list_head *pos; | ||||||
|  | 	struct disk_part *curr; | ||||||
|  | 
 | ||||||
|  | 	list_for_each(pos, &disk_partitions) { | ||||||
|  | 		curr = list_entry(pos, struct disk_part, list); | ||||||
|  | 		printf("Partition %d:\n", curr->partnum); | ||||||
|  | 		printf("1st block %x, size %x\n", (unsigned)curr->gpt_part_info.start, | ||||||
|  | 		       (unsigned)curr->gpt_part_info.size); | ||||||
|  | 		printf("Block size %lu, name %s\n", curr->gpt_part_info.blksz, | ||||||
|  | 		       curr->gpt_part_info.name); | ||||||
|  | 		printf("Type %s, bootable %d\n", curr->gpt_part_info.type, | ||||||
|  | 		       curr->gpt_part_info.bootable); | ||||||
|  | #ifdef CONFIG_PARTITION_UUIDS | ||||||
|  | 		printf("UUID %s\n", curr->gpt_part_info.uuid); | ||||||
|  | #endif | ||||||
|  | 		printf("\n"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * read partition info into disk_partitions list where | ||||||
|  |  * it can be printed or modified | ||||||
|  |  */ | ||||||
|  | static int get_gpt_info(struct blk_desc *dev_desc) | ||||||
|  | { | ||||||
|  | 	/* start partition numbering at 1, as U-Boot does */ | ||||||
|  | 	int valid_parts = 0, p, ret; | ||||||
|  | 	disk_partition_t info; | ||||||
|  | 	struct disk_part *new_disk_part; | ||||||
|  | 
 | ||||||
|  | 	if (disk_partitions.next == NULL) | ||||||
|  | 		INIT_LIST_HEAD(&disk_partitions); | ||||||
|  | 
 | ||||||
|  | 	for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) { | ||||||
|  | 		ret = part_get_info(dev_desc, p, &info); | ||||||
|  | 		if (ret) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		/* Add 1 here because counter is zero-based but p1 is
 | ||||||
|  | 		   the first partition */ | ||||||
|  | 		new_disk_part = allocate_disk_part(&info, valid_parts+1); | ||||||
|  | 		if (IS_ERR(new_disk_part)) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 		list_add_tail(&new_disk_part->list, &disk_partitions); | ||||||
|  | 		valid_parts++; | ||||||
|  | 	} | ||||||
|  | 	if (valid_parts == 0) { | ||||||
|  | 		printf("** No valid partitions found **\n"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	return valid_parts; | ||||||
|  |  out: | ||||||
|  | 	if (valid_parts >= 1) | ||||||
|  | 		del_gpt_info(); | ||||||
|  | 	return -ENODEV; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* a wrapper to test get_gpt_info */ | ||||||
|  | static int do_get_gpt_info(struct blk_desc *dev_desc) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	ret = get_gpt_info(dev_desc); | ||||||
|  | 	if (ret > 0) { | ||||||
|  | 		print_gpt_info(); | ||||||
|  | 		del_gpt_info(); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * set_gpt_info(): Fill partition information from string |  * set_gpt_info(): Fill partition information from string | ||||||
|  *		function allocates memory, remember to free! |  *		function allocates memory, remember to free! | ||||||
|  | @ -455,6 +574,10 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | ||||||
| 		printf("Verify GPT: "); | 		printf("Verify GPT: "); | ||||||
| 	} else if (strcmp(argv[1], "guid") == 0) { | 	} else if (strcmp(argv[1], "guid") == 0) { | ||||||
| 		ret = do_disk_guid(blk_dev_desc, argv[4]); | 		ret = do_disk_guid(blk_dev_desc, argv[4]); | ||||||
|  | #ifdef CONFIG_CMD_GPT_RENAME | ||||||
|  | 	} else if (strcmp(argv[1], "read") == 0) { | ||||||
|  | 		ret = do_get_gpt_info(blk_dev_desc); | ||||||
|  | #endif | ||||||
| 	} else { | 	} else { | ||||||
| 		return CMD_RET_USAGE; | 		return CMD_RET_USAGE; | ||||||
| 	} | 	} | ||||||
|  | @ -477,6 +600,8 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt, | ||||||
| 	" Example usage:\n" | 	" Example usage:\n" | ||||||
| 	" gpt write mmc 0 $partitions\n" | 	" gpt write mmc 0 $partitions\n" | ||||||
| 	" gpt verify mmc 0 $partitions\n" | 	" gpt verify mmc 0 $partitions\n" | ||||||
|  | 	" read <interface> <dev>\n" | ||||||
|  | 	"    - read GPT into a data structure for manipulation\n" | ||||||
| 	" guid <interface> <dev>\n" | 	" guid <interface> <dev>\n" | ||||||
| 	"    - print disk GUID\n" | 	"    - print disk GUID\n" | ||||||
| 	" guid <interface> <dev> <varname>\n" | 	" guid <interface> <dev> <varname>\n" | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ | ||||||
| #include <blk.h> | #include <blk.h> | ||||||
| #include <ide.h> | #include <ide.h> | ||||||
| #include <uuid.h> | #include <uuid.h> | ||||||
|  | #include <linux/list.h> | ||||||
| 
 | 
 | ||||||
| struct block_drvr { | struct block_drvr { | ||||||
| 	char *name; | 	char *name; | ||||||
|  | @ -69,6 +70,12 @@ typedef struct disk_partition { | ||||||
| #endif | #endif | ||||||
| } disk_partition_t; | } disk_partition_t; | ||||||
| 
 | 
 | ||||||
|  | struct disk_part { | ||||||
|  | 	int partnum; | ||||||
|  | 	disk_partition_t gpt_part_info; | ||||||
|  | 	struct list_head list; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /* Misc _get_dev functions */ | /* Misc _get_dev functions */ | ||||||
| #ifdef CONFIG_PARTITIONS | #ifdef CONFIG_PARTITIONS | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue