1/* SPDX-License-Identifier: GPL-2.0+ */ 2/* 3 * (C) Copyright 2000-2004 4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 5 */ 6#ifndef _PART_H 7#define _PART_H 8 9#include <blk.h> 10#include <ide.h> 11#include <uuid.h> 12#include <linker_lists.h> 13#include <linux/list.h> 14 15struct block_drvr { 16 char *name; 17 int (*select_hwpart)(int dev_num, int hwpart); 18}; 19 20#define LOG2(x) (((x & 0xaaaaaaaa) ? 1 : 0) + ((x & 0xcccccccc) ? 2 : 0) + \ 21 ((x & 0xf0f0f0f0) ? 4 : 0) + ((x & 0xff00ff00) ? 8 : 0) + \ 22 ((x & 0xffff0000) ? 16 : 0)) 23#define LOG2_INVALID(type) ((type)((sizeof(type)<<3)-1)) 24 25/* Part types */ 26#define PART_TYPE_UNKNOWN 0x00 27#define PART_TYPE_MAC 0x01 28#define PART_TYPE_DOS 0x02 29#define PART_TYPE_ISO 0x03 30#define PART_TYPE_AMIGA 0x04 31#define PART_TYPE_EFI 0x05 32 33/* maximum number of partition entries supported by search */ 34#define DOS_ENTRY_NUMBERS 8 35#define ISO_ENTRY_NUMBERS 64 36#define MAC_ENTRY_NUMBERS 64 37#define AMIGA_ENTRY_NUMBERS 8 38/* 39 * Type string for U-Boot bootable partitions 40 */ 41#define BOOT_PART_TYPE "U-Boot" /* primary boot partition type */ 42#define BOOT_PART_COMP "PPCBoot" /* PPCBoot compatibility type */ 43 44/* device types */ 45#define DEV_TYPE_UNKNOWN 0xff /* not connected */ 46#define DEV_TYPE_HARDDISK 0x00 /* harddisk */ 47#define DEV_TYPE_TAPE 0x01 /* Tape */ 48#define DEV_TYPE_CDROM 0x05 /* CD-ROM */ 49#define DEV_TYPE_OPDISK 0x07 /* optical disk */ 50 51#define PART_NAME_LEN 32 52#define PART_TYPE_LEN 32 53#define MAX_SEARCH_PARTITIONS 64 54 55#define PART_BOOTABLE ((int)BIT(0)) 56#define PART_EFI_SYSTEM_PARTITION ((int)BIT(1)) 57 58struct disk_partition { 59 lbaint_t start; /* # of first block in partition */ 60 lbaint_t size; /* number of blocks in partition */ 61 ulong blksz; /* block size in bytes */ 62 uchar name[PART_NAME_LEN]; /* partition name */ 63 uchar type[PART_TYPE_LEN]; /* string type description */ 64 /* 65 * The bootable is a bitmask with the following fields: 66 * 67 * PART_BOOTABLE the MBR bootable flag is set 68 * PART_EFI_SYSTEM_PARTITION the partition is an EFI system partition 69 */ 70 int bootable; 71#if CONFIG_IS_ENABLED(PARTITION_UUIDS) 72 char uuid[UUID_STR_LEN + 1]; /* filesystem UUID as string, if exists */ 73#endif 74#ifdef CONFIG_PARTITION_TYPE_GUID 75 char type_guid[UUID_STR_LEN + 1]; /* type GUID as string, if exists */ 76#endif 77#ifdef CONFIG_DOS_PARTITION 78 uchar sys_ind; /* partition type */ 79#endif 80}; 81 82struct disk_part { 83 int partnum; 84 struct disk_partition gpt_part_info; 85 struct list_head list; 86}; 87 88/* Misc _get_dev functions */ 89#ifdef CONFIG_PARTITIONS 90/** 91 * blk_get_dev() - get a pointer to a block device given its type and number 92 * 93 * Each interface allocates its own devices and typically struct blk_desc is 94 * contained with the interface's data structure. There is no global 95 * numbering for block devices, so the interface name must be provided. 96 * 97 * @ifname: Interface name (e.g. "ide", "scsi") 98 * @dev: Device number (0 for first device on that interface, 1 for 99 * second, etc. 100 * @return pointer to the block device, or NULL if not available, or an 101 * error occurred. 102 */ 103struct blk_desc *blk_get_dev(const char *ifname, int dev); 104 105struct blk_desc *mg_disk_get_dev(int dev); 106int host_get_dev_err(int dev, struct blk_desc **blk_devp); 107 108/* disk/part.c */ 109int part_get_info(struct blk_desc *dev_desc, int part, 110 struct disk_partition *info); 111/** 112 * part_get_info_whole_disk() - get partition info for the special case of 113 * a partition occupying the entire disk. 114 */ 115int part_get_info_whole_disk(struct blk_desc *dev_desc, 116 struct disk_partition *info); 117 118void part_print(struct blk_desc *dev_desc); 119void part_init(struct blk_desc *dev_desc); 120void dev_print(struct blk_desc *dev_desc); 121 122/** 123 * blk_get_device_by_str() - Get a block device given its interface/hw partition 124 * 125 * Each interface allocates its own devices and typically struct blk_desc is 126 * contained with the interface's data structure. There is no global 127 * numbering for block devices, so the interface name must be provided. 128 * 129 * The hardware parition is not related to the normal software partitioning 130 * of a device - each hardware partition is effectively a separately 131 * accessible block device. When a hardware parition is selected on MMC the 132 * other hardware partitions become inaccessible. The same block device is 133 * used to access all hardware partitions, but its capacity may change when a 134 * different hardware partition is selected. 135 * 136 * When a hardware partition number is given, the block device switches to 137 * that hardware partition. 138 * 139 * @ifname: Interface name (e.g. "ide", "scsi") 140 * @dev_str: Device and optional hw partition. This can either be a string 141 * containing the device number (e.g. "2") or the device number 142 * and hardware partition number (e.g. "2.4") for devices that 143 * support it (currently only MMC). 144 * @dev_desc: Returns a pointer to the block device on success 145 * @return block device number (local to the interface), or -1 on error 146 */ 147int blk_get_device_by_str(const char *ifname, const char *dev_str, 148 struct blk_desc **dev_desc); 149 150/** 151 * blk_get_device_part_str() - Get a block device and partition 152 * 153 * This calls blk_get_device_by_str() to look up a device. It also looks up 154 * a partition and returns information about it. 155 * 156 * @dev_part_str is in the format: 157 * <dev>.<hw_part>:<part> where <dev> is the device number, 158 * <hw_part> is the optional hardware partition number and 159 * <part> is the partition number 160 * 161 * If ifname is "hostfs" then this function returns the sandbox host block 162 * device. 163 * 164 * If ifname is ubi, then this function returns 0, with @info set to a 165 * special UBI device. 166 * 167 * If @dev_part_str is NULL or empty or "-", then this function looks up 168 * the "bootdevice" environment variable and uses that string instead. 169 * 170 * If the partition string is empty then the first partition is used. If the 171 * partition string is "auto" then the first bootable partition is used. 172 * 173 * @ifname: Interface name (e.g. "ide", "scsi") 174 * @dev_part_str: Device and partition string 175 * @dev_desc: Returns a pointer to the block device on success 176 * @info: Returns partition information 177 * @allow_whole_dev: true to allow the user to select partition 0 178 * (which means the whole device), false to require a valid 179 * partition number >= 1 180 * @return partition number, or -1 on error 181 * 182 */ 183int blk_get_device_part_str(const char *ifname, const char *dev_part_str, 184 struct blk_desc **dev_desc, 185 struct disk_partition *info, int allow_whole_dev); 186 187/** 188 * part_get_info_by_name_type() - Search for a partition by name 189 * for only specified partition type 190 * 191 * @param dev_desc - block device descriptor 192 * @param gpt_name - the specified table entry name 193 * @param info - returns the disk partition info 194 * @param part_type - only search in partitions of this type 195 * 196 * @return - the partition number on match (starting on 1), -1 on no match, 197 * otherwise error 198 */ 199int part_get_info_by_name_type(struct blk_desc *dev_desc, const char *name, 200 struct disk_partition *info, int part_type); 201 202/** 203 * part_get_info_by_name() - Search for a partition by name 204 * among all available registered partitions 205 * 206 * @param dev_desc - block device descriptor 207 * @param gpt_name - the specified table entry name 208 * @param info - returns the disk partition info 209 * 210 * @return - the partition number on match (starting on 1), -1 on no match, 211 * otherwise error 212 */ 213int part_get_info_by_name(struct blk_desc *dev_desc, 214 const char *name, struct disk_partition *info); 215 216/** 217 * Get partition info from dev number + part name, or dev number + part number. 218 * 219 * Parse a device number and partition description (either name or number) 220 * in the form of device number plus partition name separated by a "#" 221 * (like "device_num#partition_name") or a device number plus a partition number 222 * separated by a ":". For example both "0#misc" and "0:1" can be valid 223 * partition descriptions for a given interface. If the partition is found, sets 224 * dev_desc and part_info accordingly with the information of the partition. 225 * 226 * @param[in] dev_iface Device interface 227 * @param[in] dev_part_str Input partition description, like "0#misc" or "0:1" 228 * @param[out] dev_desc Place to store the device description pointer 229 * @param[out] part_info Place to store the partition information 230 * @param[in] allow_whole_dev true to allow the user to select partition 0 231 * (which means the whole device), false to require a valid 232 * partition number >= 1 233 * @return the partition number on success, or negative errno on error 234 */ 235int part_get_info_by_dev_and_name_or_num(const char *dev_iface, 236 const char *dev_part_str, 237 struct blk_desc **dev_desc, 238 struct disk_partition *part_info, 239 int allow_whole_dev); 240 241/** 242 * part_set_generic_name() - create generic partition like hda1 or sdb2 243 * 244 * Helper function for partition tables, which don't hold partition names 245 * (DOS, ISO). Generates partition name out of the device type and partition 246 * number. 247 * 248 * @dev_desc: pointer to the block device 249 * @part_num: partition number for which the name is generated 250 * @name: buffer where the name is written 251 */ 252void part_set_generic_name(const struct blk_desc *dev_desc, 253 int part_num, char *name); 254 255extern const struct block_drvr block_drvr[]; 256#else 257static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) 258{ return NULL; } 259static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } 260 261static inline int part_get_info(struct blk_desc *dev_desc, int part, 262 struct disk_partition *info) { return -1; } 263static inline int part_get_info_whole_disk(struct blk_desc *dev_desc, 264 struct disk_partition *info) 265{ return -1; } 266static inline void part_print(struct blk_desc *dev_desc) {} 267static inline void part_init(struct blk_desc *dev_desc) {} 268static inline void dev_print(struct blk_desc *dev_desc) {} 269static inline int blk_get_device_by_str(const char *ifname, const char *dev_str, 270 struct blk_desc **dev_desc) 271{ return -1; } 272static inline int blk_get_device_part_str(const char *ifname, 273 const char *dev_part_str, 274 struct blk_desc **dev_desc, 275 struct disk_partition *info, 276 int allow_whole_dev) 277{ *dev_desc = NULL; return -1; } 278static inline int 279part_get_info_by_dev_and_name_or_num(const char *dev_iface, 280 const char *dev_part_str, 281 struct blk_desc **dev_desc, 282 struct disk_partition *part_info, 283 int allow_whole_dev) 284{ 285 *dev_desc = NULL; 286 return -ENOSYS; 287} 288#endif 289 290/* 291 * We don't support printing partition information in SPL and only support 292 * getting partition information in a few cases. 293 */ 294#ifdef CONFIG_SPL_BUILD 295# define part_print_ptr(x) NULL 296# if defined(CONFIG_SPL_FS_EXT4) || defined(CONFIG_SPL_FS_FAT) || \ 297 defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION) 298# define part_get_info_ptr(x) x 299# else 300# define part_get_info_ptr(x) NULL 301# endif 302#else 303#define part_print_ptr(x) x 304#define part_get_info_ptr(x) x 305#endif 306 307 308struct part_driver { 309 const char *name; 310 int part_type; 311 const int max_entries; /* maximum number of entries to search */ 312 313 /** 314 * get_info() - Get information about a partition 315 * 316 * @dev_desc: Block device descriptor 317 * @part: Partition number (1 = first) 318 * @info: Returns partition information 319 */ 320 int (*get_info)(struct blk_desc *dev_desc, int part, 321 struct disk_partition *info); 322 323 /** 324 * print() - Print partition information 325 * 326 * @dev_desc: Block device descriptor 327 */ 328 void (*print)(struct blk_desc *dev_desc); 329 330 /** 331 * test() - Test if a device contains this partition type 332 * 333 * @dev_desc: Block device descriptor 334 * @return 0 if the block device appears to contain this partition 335 * type, -ve if not 336 */ 337 int (*test)(struct blk_desc *dev_desc); 338}; 339 340/* Declare a new U-Boot partition 'driver' */ 341#define U_BOOT_PART_TYPE(__name) \ 342 ll_entry_declare(struct part_driver, __name, part_driver) 343 344#include <part_efi.h> 345 346#if CONFIG_IS_ENABLED(EFI_PARTITION) 347/* disk/part_efi.c */ 348/** 349 * write_gpt_table() - Write the GUID Partition Table to disk 350 * 351 * @param dev_desc - block device descriptor 352 * @param gpt_h - pointer to GPT header representation 353 * @param gpt_e - pointer to GPT partition table entries 354 * 355 * @return - zero on success, otherwise error 356 */ 357int write_gpt_table(struct blk_desc *dev_desc, 358 gpt_header *gpt_h, gpt_entry *gpt_e); 359 360/** 361 * gpt_fill_pte(): Fill the GPT partition table entry 362 * 363 * @param dev_desc - block device descriptor 364 * @param gpt_h - GPT header representation 365 * @param gpt_e - GPT partition table entries 366 * @param partitions - list of partitions 367 * @param parts - number of partitions 368 * 369 * @return zero on success 370 */ 371int gpt_fill_pte(struct blk_desc *dev_desc, 372 gpt_header *gpt_h, gpt_entry *gpt_e, 373 struct disk_partition *partitions, int parts); 374 375/** 376 * gpt_fill_header(): Fill the GPT header 377 * 378 * @param dev_desc - block device descriptor 379 * @param gpt_h - GPT header representation 380 * @param str_guid - disk guid string representation 381 * @param parts_count - number of partitions 382 * 383 * @return - error on str_guid conversion error 384 */ 385int gpt_fill_header(struct blk_desc *dev_desc, gpt_header *gpt_h, 386 char *str_guid, int parts_count); 387 388/** 389 * gpt_restore(): Restore GPT partition table 390 * 391 * @param dev_desc - block device descriptor 392 * @param str_disk_guid - disk GUID 393 * @param partitions - list of partitions 394 * @param parts - number of partitions 395 * 396 * @return zero on success 397 */ 398int gpt_restore(struct blk_desc *dev_desc, char *str_disk_guid, 399 struct disk_partition *partitions, const int parts_count); 400 401/** 402 * is_valid_gpt_buf() - Ensure that the Primary GPT information is valid 403 * 404 * @param dev_desc - block device descriptor 405 * @param buf - buffer which contains the MBR and Primary GPT info 406 * 407 * @return - '0' on success, otherwise error 408 */ 409int is_valid_gpt_buf(struct blk_desc *dev_desc, void *buf); 410 411/** 412 * write_mbr_and_gpt_partitions() - write MBR, Primary GPT and Backup GPT 413 * 414 * @param dev_desc - block device descriptor 415 * @param buf - buffer which contains the MBR and Primary GPT info 416 * 417 * @return - '0' on success, otherwise error 418 */ 419int write_mbr_and_gpt_partitions(struct blk_desc *dev_desc, void *buf); 420 421/** 422 * gpt_verify_headers() - Function to read and CRC32 check of the GPT's header 423 * and partition table entries (PTE) 424 * 425 * As a side effect if sets gpt_head and gpt_pte so they point to GPT data. 426 * 427 * @param dev_desc - block device descriptor 428 * @param gpt_head - pointer to GPT header data read from medium 429 * @param gpt_pte - pointer to GPT partition table enties read from medium 430 * 431 * @return - '0' on success, otherwise error 432 */ 433int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head, 434 gpt_entry **gpt_pte); 435 436/** 437 * gpt_verify_partitions() - Function to check if partitions' name, start and 438 * size correspond to '$partitions' env variable 439 * 440 * This function checks if on medium stored GPT data is in sync with information 441 * provided in '$partitions' environment variable. Specificially, name, start 442 * and size of the partition is checked. 443 * 444 * @param dev_desc - block device descriptor 445 * @param partitions - partition data read from '$partitions' env variable 446 * @param parts - number of partitions read from '$partitions' env variable 447 * @param gpt_head - pointer to GPT header data read from medium 448 * @param gpt_pte - pointer to GPT partition table enties read from medium 449 * 450 * @return - '0' on success, otherwise error 451 */ 452int gpt_verify_partitions(struct blk_desc *dev_desc, 453 struct disk_partition *partitions, int parts, 454 gpt_header *gpt_head, gpt_entry **gpt_pte); 455 456 457/** 458 * get_disk_guid() - Function to read the GUID string from a device's GPT 459 * 460 * This function reads the GUID string from a block device whose descriptor 461 * is provided. 462 * 463 * @param dev_desc - block device descriptor 464 * @param guid - pre-allocated string in which to return the GUID 465 * 466 * @return - '0' on success, otherwise error 467 */ 468int get_disk_guid(struct blk_desc *dev_desc, char *guid); 469 470#endif 471 472#if CONFIG_IS_ENABLED(DOS_PARTITION) 473/** 474 * is_valid_dos_buf() - Ensure that a DOS MBR image is valid 475 * 476 * @param buf - buffer which contains the MBR 477 * 478 * @return - '0' on success, otherwise error 479 */ 480int is_valid_dos_buf(void *buf); 481 482/** 483 * write_mbr_sector() - write DOS MBR 484 * 485 * @param dev_desc - block device descriptor 486 * @param buf - buffer which contains the MBR 487 * 488 * @return - '0' on success, otherwise error 489 */ 490int write_mbr_sector(struct blk_desc *dev_desc, void *buf); 491 492int write_mbr_partitions(struct blk_desc *dev, 493 struct disk_partition *p, int count, unsigned int disksig); 494int layout_mbr_partitions(struct disk_partition *p, int count, 495 lbaint_t total_sectors); 496 497#endif 498 499#ifdef CONFIG_PARTITIONS 500/** 501 * part_driver_get_count() - get partition driver count 502 * 503 * @return - number of partition drivers 504 */ 505static inline int part_driver_get_count(void) 506{ 507 return ll_entry_count(struct part_driver, part_driver); 508} 509 510/** 511 * part_driver_get_first() - get first partition driver 512 * 513 * @return - pointer to first partition driver on success, otherwise NULL 514 */ 515static inline struct part_driver *part_driver_get_first(void) 516{ 517 return ll_entry_start(struct part_driver, part_driver); 518} 519 520#else 521static inline int part_driver_get_count(void) 522{ return 0; } 523 524static inline struct part_driver *part_driver_get_first(void) 525{ return NULL; } 526#endif /* CONFIG_PARTITIONS */ 527 528#endif /* _PART_H */ 529