Changeset 6453e306 in mainline for uspace/lib/gpt
- Timestamp:
- 2013-12-25T16:09:43Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- ac36aed
- Parents:
- d51beba3
- Location:
- uspace/lib/gpt
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/gpt/global.c
rd51beba3 r6453e306 1 1 /* 2 * Copyright (c) 2011 , 2012,2013 Dominik Taborsky2 * Copyright (c) 2011-2013 Dominik Taborsky 3 3 * All rights reserved. 4 4 * … … 44 44 }; 45 45 46 const struct partition_typegpt_ptypes[] = {47 { " Unused entry","00000000" "0000" "0000" "0000000000000000" }, /* 0 */48 { "HelenOS System", "656C6548" "4F6E" "5320" "53797374656D0000" }, /* 1 It says "HelenOS System\0\0"*/49 { "MBR partition scheme", "024DEE41" "33E7" "11D3" "9D690008C781F39F" },50 { "EFI System", "C12A7328" "F81F" "11D2" "BA4B00A0C93EC93B" },51 { "BIOS Boot", "21686148" "6449" "6E6F" "744E656564454649" },52 { "Windows Reserved", "E3C9E316" "0B5C" "4DB8" "817DF92DF00215AE" },53 { "Windows Basic data", "EBD0A0A2" "B9E5" "4433" "87C068B6B72699C7" },54 { "Windows LDM metadata", "5808C8AA" "7E8F" "42E0" "85D2E1E90434CFB3" },55 { "Windows LDM data", "AF9B60A0" "1431" "4F62" "BC683311714A69AD" },56 { "Windows Recovery Environment", "DE94BBA4" "06D1" "4D40" "A16ABFD50179D6AC" },57 { "Windows IBM GPFS", "37AFFC90" "EF7D" "4E96" "91C32D7AE055B174" }, /* 10 */58 { "Windows Cluster metadata", "DB97DBA9" "0840" "4BAE" "97F0FFB9A327C7E1" },59 { "HP-UX Data", "75894C1E" "3AEB" "11D3" "B7C17B03A0000000" },60 { "HP-UX Service", "E2A1E728" "32E3" "11D6" "A6827B03A0000000" },61 { "Linux filesystem data", "0FC63DAF" "8483" "4772" "8E793D69D8477DE4" },62 { "Linux RAID", "A19D880F" "05FC" "4D3B" "A006743F0F84911E" },63 { "Linux Swap", "0657FD6D" "A4AB" "43C4" "84E50933C84B4F4F" },64 { "Linux LVM", "E6D6D379" "F507" "44C2" "A23C238F2A3DF928" },65 { "Linux filesystem data", "933AC7E1" "2EB4" "4F13" "B8440E14E2AEF915" },66 { "Linux Reserved", "8DA63339" "0007" "60C0" "C436083AC8230908" },67 { "FreeBSD Boot", "83BD6B9D" "7F41" "11DC" "BE0B001560B84F0F" }, /* 20 */68 { "FreeBSD Data", "516E7CB4" "6ECF" "11D6" "8FF800022D09712B" },69 { "FreeBSD Swap", "516E7CB5" "6ECF" "11D6" "8FF800022D09712B" },70 { "FreeBSD UFS", "516E7CB6" "6ECF" "11D6" "8FF800022D09712B" },71 { "FreeBSD Vinum VM", "516E7CB8" "6ECF" "11D6" "8FF800022D09712B" },72 { "FreeBSD ZFS", "516E7CBA" "6ECF" "11D6" "8FF800022D09712B" },73 { "Mac OS X HFS+", "48465300" "0000" "11AA" "AA1100306543ECAC" },74 { "Mac OS X UFS", "55465300" "0000" "11AA" "AA1100306543ECAC" },75 { "Mac OS X ZFS", "6A898CC3" "1DD2" "11B2" "99A6080020736631" },76 { "Mac OS X RAID", "52414944" "0000" "11AA" "AA1100306543ECAC" },77 { "Mac OS X RAID, offline", "52414944" "5F4F" "11AA" "AA1100306543ECAC" }, /* 30 */78 { "Mac OS X Boot", "426F6F74" "0000" "11AA" "AA1100306543ECAC" },79 { "Mac OS X Label", "4C616265" "6C00" "11AA" "AA1100306543ECAC" },80 { "Mac OS X TV Recovery", "5265636F" "7665" "11AA" "AA1100306543ECAC" },81 { "Mac OS X Core Storage", "53746F72" "6167" "11AA" "AA1100306543ECAC" },82 { "Solaris Boot", "6A82CB45" "1DD2" "11B2" "99A6080020736631" },83 { "Solaris Root", "6A85CF4D" "1DD2" "11B2" "99A6080020736631" },84 { "Solaris Swap", "6A87C46F" "1DD2" "11B2" "99A6080020736631" },85 { "Solaris Backup", "6A8B642B" "1DD2" "11B2" "99A6080020736631" },86 { "Solaris /usr", "6A898CC3" "1DD2" "11B2" "99A6080020736631" },87 { "Solaris /var", "6A8EF2E9" "1DD2" "11B2" "99A6080020736631" }, /* 40 */88 { "Solaris /home", "6A90BA39" "1DD2" "11B2" "99A6080020736631" },89 { "Solaris Alternate sector", "6A9283A5" "1DD2" "11B2" "99A6080020736631" },90 { "Solaris Reserved", "6A945A3B" "1DD2" "11B2" "99A6080020736631" },91 { "Solaris Reserved", "6A9630D1" "1DD2" "11B2" "99A6080020736631" },92 { "Solaris Reserved", "6A980767" "1DD2" "11B2" "99A6080020736631" },93 { "Solaris Reserved", "6A96237F" "1DD2" "11B2" "99A6080020736631" },94 { "Solaris Reserved", "6A8D2AC7" "1DD2" "11B2" "99A6080020736631" },95 { "NetBSD Swap", "49F48D32" "B10E" "11DC" "B99B0019D1879648" },96 { "NetBSD FFS", "49F48D5A" "B10E" "11DC" "B99B0019D1879648" },97 { "NetBSD LFS", "49F48D82" "B10E" "11DC" "B99B0019D1879648" }, /* 50 */98 { "NetBSD RAID", "49F48DAA" "B10E" "11DC" "B99B0019D1879648" },99 { "NetBSD Concatenated", "2DB519C4" "B10F" "11DC" "B99B0019D1879648" },100 { "NetBSD Encrypted", "2DB519EC" "B10F" "11DC" "B99B0019D1879648" },101 { "ChromeOS ChromeOS kernel", "FE3A2A5D" "4F32" "41A7" "B725ACCC3285A309" },102 { "ChromeOS rootfs", "3CB8E202" "3B7E" "47DD" "8A3C7FF2A13CFCEC" },103 { "ChromeOS future use", "2E0A753D" "9E48" "43B0" "8337B15192CB1B5E" },104 { "MidnightBSD Boot", "85D5E45E" "237C" "11E1" "B4B3E89A8F7FC3A7" },105 { "MidnightBSD Data", "85D5E45A" "237C" "11E1" "B4B3E89A8F7FC3A7" },106 { "MidnightBSD Swap", "85D5E45B" "237C" "11E1" "B4B3E89A8F7FC3A7" },107 { "MidnightBSD UFS", "0394Ef8B" "237E" "11E1" "B4B3E89A8F7FC3A7" }, /* 60 */108 { "MidnightBSD Vinum VM", "85D5E45C" "237C" "11E1" "B4B3E89A8F7FC3A7" },109 { "MidnightBSD ZFS", "85D5E45D" "237C" "11E1" "B4B3E89A8F7FC3A7" },110 { " Uknown", NULL} /* keep this as the last one! gpt_get_part_type depends on it!*/46 const partition_type_t gpt_ptypes[] = { 47 { "unused entry", "00000000" "0000" "0000" "0000000000000000" }, /* 0 */ 48 { "HelenOS System", "3dc61fa0" "cf7a" "3ad8" "ac57615029d81a6b" }, /* "HelenOS System" encoded as RFC 4122 UUID, version 3 (MD5 name-based) */ 49 { "MBR partition scheme", "024dee41" "33e7" "11d3" "9d690008c781f39f" }, 50 { "EFI System", "c12a7328" "f81f" "11d2" "ba4b00a0c93ec93b" }, 51 { "BIOS Boot", "21686148" "6449" "6e6f" "744e656564454649" }, 52 { "Windows Reserved", "e3c9e316" "0b5c" "4db8" "817df92df00215ae" }, 53 { "Windows Basic data", "ebd0a0a2" "b9e5" "4433" "87c068b6b72699c7" }, 54 { "Windows LDM metadata", "5808c8aa" "7e8f" "42e0" "85d2e1e90434cfb3" }, 55 { "Windows LDM data", "af9b60a0" "1431" "4f62" "bc683311714a69ad" }, 56 { "Windows Recovery Environment", "de94bba4" "06d1" "4d40" "a16abfd50179d6ac" }, 57 { "Windows IBM GPFS", "37affc90" "ef7d" "4e96" "91c32d7ae055b174" }, /* 10 */ 58 { "Windows Cluster metadata", "db97dba9" "0840" "4bae" "97f0ffb9a327c7e1" }, 59 { "HP-UX Data", "75894c1e" "3aeb" "11d3" "b7c17b03a0000000" }, 60 { "HP-UX Service", "e2a1e728" "32e3" "11d6" "a6827b03a0000000" }, 61 { "Linux filesystem data", "0fc63daf" "8483" "4772" "8e793d69d8477de4" }, 62 { "Linux RAID", "a19d880f" "05fc" "4d3b" "a006743f0f84911e" }, 63 { "Linux Swap", "0657fd6d" "a4ab" "43c4" "84e50933c84b4f4f" }, 64 { "Linux LVM", "e6d6d379" "f507" "44c2" "a23c238f2a3df928" }, 65 { "Linux filesystem data", "933ac7e1" "2eb4" "4f13" "b8440e14e2aef915" }, 66 { "Linux Reserved", "8da63339" "0007" "60c0" "c436083ac8230908" }, 67 { "FreeBSD Boot", "83bd6b9d" "7f41" "11dc" "be0b001560b84f0f" }, /* 20 */ 68 { "FreeBSD Data", "516e7cb4" "6ecf" "11d6" "8ff800022d09712b" }, 69 { "FreeBSD Swap", "516e7cb5" "6ecf" "11d6" "8ff800022d09712b" }, 70 { "FreeBSD UFS", "516e7cb6" "6ecf" "11d6" "8ff800022d09712b" }, 71 { "FreeBSD Vinum VM", "516e7cb8" "6ecf" "11d6" "8ff800022d09712b" }, 72 { "FreeBSD ZFS", "516e7cba" "6ecf" "11d6" "8ff800022d09712b" }, 73 { "Mac OS X HFS+", "48465300" "0000" "11aa" "aa1100306543ecac" }, 74 { "Mac OS X UFS", "55465300" "0000" "11aa" "aa1100306543ecac" }, 75 { "Mac OS X ZFS", "6a898cc3" "1dd2" "11b2" "99a6080020736631" }, 76 { "Mac OS X RAID", "52414944" "0000" "11aa" "aa1100306543ecac" }, 77 { "Mac OS X RAID, offline", "52414944" "5f4f" "11aa" "aa1100306543ecac" }, /* 30 */ 78 { "Mac OS X Boot", "426f6f74" "0000" "11aa" "aa1100306543ecac" }, 79 { "Mac OS X Label", "4c616265" "6c00" "11aa" "aa1100306543ecac" }, 80 { "Mac OS X TV Recovery", "5265636f" "7665" "11aa" "aa1100306543ecac" }, 81 { "Mac OS X Core Storage", "53746f72" "6167" "11aa" "aa1100306543ecac" }, 82 { "Solaris Boot", "6a82cb45" "1dd2" "11b2" "99a6080020736631" }, 83 { "Solaris Root", "6a85cf4d" "1dd2" "11b2" "99a6080020736631" }, 84 { "Solaris Swap", "6a87c46f" "1dd2" "11b2" "99a6080020736631" }, 85 { "Solaris Backup", "6a8b642b" "1dd2" "11b2" "99a6080020736631" }, 86 { "Solaris /usr", "6a898cc3" "1dd2" "11b2" "99a6080020736631" }, 87 { "Solaris /var", "6a8ef2e9" "1dd2" "11b2" "99a6080020736631" }, /* 40 */ 88 { "Solaris /home", "6a90ba39" "1dd2" "11b2" "99a6080020736631" }, 89 { "Solaris Alternate sector", "6a9283a5" "1dd2" "11b2" "99a6080020736631" }, 90 { "Solaris Reserved", "6a945a3b" "1dd2" "11b2" "99a6080020736631" }, 91 { "Solaris Reserved", "6a9630d1" "1dd2" "11b2" "99a6080020736631" }, 92 { "Solaris Reserved", "6a980767" "1dd2" "11b2" "99a6080020736631" }, 93 { "Solaris Reserved", "6a96237f" "1dd2" "11b2" "99a6080020736631" }, 94 { "Solaris Reserved", "6a8d2ac7" "1dd2" "11b2" "99a6080020736631" }, 95 { "NetBSD Swap", "49f48d32" "b10e" "11dc" "b99b0019d1879648" }, 96 { "NetBSD FFS", "49f48d5a" "b10e" "11dc" "b99b0019d1879648" }, 97 { "NetBSD LFS", "49f48d82" "b10e" "11dc" "b99b0019d1879648" }, /* 50 */ 98 { "NetBSD RAID", "49f48daa" "b10e" "11dc" "b99b0019d1879648" }, 99 { "NetBSD Concatenated", "2db519c4" "b10f" "11dc" "b99b0019d1879648" }, 100 { "NetBSD Encrypted", "2db519ec" "b10f" "11dc" "b99b0019d1879648" }, 101 { "ChromeOS ChromeOS kernel", "fe3a2a5d" "4f32" "41a7" "b725accc3285a309" }, 102 { "ChromeOS rootfs", "3cb8e202" "3b7e" "47dd" "8a3c7ff2a13cfcec" }, 103 { "ChromeOS future use", "2e0a753d" "9e48" "43b0" "8337b15192cb1b5e" }, 104 { "MidnightBSD Boot", "85d5e45e" "237c" "11e1" "b4b3e89a8f7fc3a7" }, 105 { "MidnightBSD Data", "85d5e45a" "237c" "11e1" "b4b3e89a8f7fc3a7" }, 106 { "MidnightBSD Swap", "85d5e45b" "237c" "11e1" "b4b3e89a8f7fc3a7" }, 107 { "MidnightBSD UFS", "0394ef8b" "237e" "11e1" "b4b3e89a8f7fc3a7" }, /* 60 */ 108 { "MidnightBSD Vinum VM", "85d5e45c" "237c" "11e1" "b4b3e89a8f7fc3a7" }, 109 { "MidnightBSD ZFS", "85d5e45d" "237c" "11e1" "b4b3e89a8f7fc3a7" }, 110 { "unknown entry", NULL } /* Keep this as the last entry */ 111 111 }; 112 113 114 -
uspace/lib/gpt/gpt.h
rd51beba3 r6453e306 1 1 /* 2 2 * Copyright (c) 2009 Jiri Svoboda 3 * Copyright (c) 2011 , 2012,2013 Dominik Taborsky3 * Copyright (c) 2011-2013 Dominik Taborsky 4 4 * All rights reserved. 5 5 * … … 43 43 AT_UNDEFINED, 44 44 AT_SPECIFIC = 48 45 } GPT_ATTR;45 } gpt_attr_t; 46 46 47 /** GPT header 48 * - all in little endian. 49 */ 47 /** GPT header */ 50 48 typedef struct { 51 uint8_t efi_signature[8];52 uint8_t revision[4];49 uint8_t efi_signature[8]; 50 uint8_t revision[4]; 53 51 uint32_t header_size; 54 52 uint32_t header_crc32; 55 53 uint32_t reserved; 56 uint64_t my_lba;54 uint64_t current_lba; 57 55 uint64_t alternate_lba; 58 56 uint64_t first_usable_lba; 59 57 uint64_t last_usable_lba; 60 uint8_t disk_guid[16];58 uint8_t disk_guid[16]; 61 59 uint64_t entry_lba; 62 60 uint32_t fillries; … … 76 74 77 75 #endif 78 79 -
uspace/lib/gpt/libgpt.c
rd51beba3 r6453e306 1 1 /* 2 * Copyright (c) 2011 , 2012,2013 Dominik Taborsky2 * Copyright (c) 2011-2013 Dominik Taborsky 3 3 * All rights reserved. 4 4 * … … 34 34 35 35 /* TODO: 36 * Th is implementation only supports fixed size partition entries. Specification37 * requires otherwise, though. Use void * array and casting to achieve that.36 * The implementation currently supports fixed size partition entries only. 37 * The specification requires otherwise, though. 38 38 */ 39 39 … … 46 46 #include <assert.h> 47 47 #include <byteorder.h> 48 #include < checksum.h>48 #include <adt/checksum.h> 49 49 #include <mem.h> 50 50 #include <sys/typefmt.h> 51 51 #include <mbr.h> 52 53 52 #include <align.h> 54 53 #include "libgpt.h" 55 54 56 55 static int load_and_check_header(service_id_t, aoff64_t, size_t, gpt_header_t *); 57 static gpt_partitions_t * alloc_part_array(uint32_t);56 static gpt_partitions_t *alloc_part_array(uint32_t); 58 57 static int extend_part_array(gpt_partitions_t *); 59 58 static int reduce_part_array(gpt_partitions_t *); … … 62 61 static bool check_encaps(gpt_part_t *, uint64_t, uint64_t); 63 62 64 /** Allocate memory for gptlabel */65 gpt_label_t * gpt_alloc_label(void)63 /** Allocate a GPT label */ 64 gpt_label_t *gpt_alloc_label(void) 66 65 { 67 66 gpt_label_t *label = malloc(sizeof(gpt_label_t)); … … 69 68 return NULL; 70 69 71 /* This is necessary so that gpt_part_foreach does not segfault */72 70 label->parts = gpt_alloc_partitions(); 73 if (label == NULL) {71 if (label->parts == NULL) { 74 72 free(label); 75 73 return NULL; … … 77 75 78 76 label->gpt = NULL; 79 80 77 label->device = 0; 81 78 … … 83 80 } 84 81 85 /** Free gpt_label_t structure*/82 /** Free a GPT label */ 86 83 void gpt_free_label(gpt_label_t *label) 87 84 { … … 95 92 } 96 93 97 /** Allocate memory for gptheader */98 gpt_t * gpt_alloc_header(size_t size)94 /** Allocate a GPT header */ 95 gpt_t *gpt_alloc_header(size_t size) 99 96 { 100 97 gpt_t *gpt = malloc(sizeof(gpt_t)); … … 102 99 return NULL; 103 100 104 /* 105 * We might need only sizeof(gpt_header_t), but we should follow 101 /* 102 * We might need only sizeof(gpt_header_t), but we should follow 106 103 * specs and have zeroes through all the rest of the block 107 104 */ 108 size_t final_size = size > sizeof(gpt_header_t) ? size : sizeof(gpt_header_t);105 size_t final_size = max(size, sizeof(gpt_header_t)); 109 106 gpt->header = malloc(final_size); 110 107 if (gpt->header == NULL) { … … 113 110 } 114 111 115 /* Enter some sane defaults. */116 112 memset(gpt->header, 0, final_size); 117 113 memcpy(gpt->header->efi_signature, efi_signature, 8); … … 121 117 gpt->header->entry_size = host2uint32_t_le(sizeof(gpt_entry_t)); 122 118 123 124 119 return gpt; 125 120 } 126 121 127 /** free() GPT header including gpt->header_lba*/122 /** Free a GPT header */ 128 123 void gpt_free_gpt(gpt_t *gpt) 129 124 { … … 132 127 } 133 128 134 /** Read GPT from specific device 135 * @param label label structure to fill 136 * @param dev_handle device to read GPT from 137 * 138 * @return EOK on success, errorcode on error 129 /** Read GPT from a device 130 * 131 * @param label Label to read. 132 * @param dev_handle Device to read GPT from. 133 * 134 * @return EOK on success, error code on error. 135 * 139 136 */ 140 137 int gpt_read_header(gpt_label_t *label, service_id_t dev_handle) 141 138 { 142 int rc; 143 size_t b_size; 144 145 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 146 if (rc != EOK) 147 goto fail; 148 149 rc = block_get_bsize(dev_handle, &b_size); 150 if (rc != EOK) 151 goto fini_fail; 139 int rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 140 if (rc != EOK) 141 return rc; 142 143 size_t block_size; 144 rc = block_get_bsize(dev_handle, &block_size); 145 if (rc != EOK) 146 goto end; 152 147 153 148 if (label->gpt == NULL) { 154 label->gpt = gpt_alloc_header(b _size);149 label->gpt = gpt_alloc_header(block_size); 155 150 if (label->gpt == NULL) { 156 151 rc = ENOMEM; 157 goto fini_fail;152 goto end; 158 153 } 159 154 } 160 155 161 rc = load_and_check_header(dev_handle, GPT_HDR_BA, b_size, label->gpt->header); 162 if (rc == EBADCHECKSUM || rc == EINVAL) { 163 aoff64_t n_blocks; 164 rc = block_get_nblocks(dev_handle, &n_blocks); 165 if (rc != EOK) 166 goto free_fail; 167 168 rc = load_and_check_header(dev_handle, n_blocks - 1, b_size, label->gpt->header); 169 if (rc == EBADCHECKSUM || rc == EINVAL) 170 goto free_fail; 156 rc = load_and_check_header(dev_handle, GPT_HDR_BA, block_size, 157 label->gpt->header); 158 if ((rc == EBADCHECKSUM) || (rc == EINVAL)) { 159 aoff64_t blocks; 160 rc = block_get_nblocks(dev_handle, &blocks); 161 if (rc != EOK) { 162 gpt_free_gpt(label->gpt); 163 goto end; 164 } 165 166 rc = load_and_check_header(dev_handle, blocks - 1, block_size, 167 label->gpt->header); 168 if ((rc == EBADCHECKSUM) || (rc == EINVAL)) { 169 gpt_free_gpt(label->gpt); 170 goto end; 171 } 171 172 } 172 173 173 174 label->device = dev_handle; 175 rc = EOK; 176 177 end: 174 178 block_fini(dev_handle); 175 return EOK;176 177 free_fail:178 gpt_free_gpt(label->gpt);179 label->gpt = NULL;180 fini_fail:181 block_fini(dev_handle);182 fail:183 179 return rc; 184 180 } 185 181 186 182 /** Write GPT header to device 187 * @param label GPT label header to be written188 * @param dev_handle device handle to write the data to189 * 190 * @return EOK on success, libblock error code otherwise191 * 192 * Note: Firstly write partitions (if modified), then gpt header.183 * 184 * @param label Label to be written. 185 * @param dev_handle Device to write the GPT to. 186 * 187 * @return EOK on success, libblock error code otherwise. 188 * 193 189 */ 194 190 int gpt_write_header(gpt_label_t *label, service_id_t dev_handle) 195 191 { 196 int rc;197 size_t b_size;198 199 192 /* The comm_size argument (the last one) is ignored */ 200 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 4096);201 if ( rc != EOK && rc != EEXIST)193 int rc = block_init(EXCHANGE_ATOMIC, dev_handle, 4096); 194 if ((rc != EOK) && (rc != EEXIST)) 202 195 return rc; 203 196 204 rc = block_get_bsize(dev_handle, &b_size); 205 if (rc != EOK) 206 return rc; 207 208 aoff64_t n_blocks; 209 rc = block_get_nblocks(dev_handle, &n_blocks); 210 if (rc != EOK) { 211 block_fini(dev_handle); 212 return rc; 213 } 214 215 uint64_t tmp; 197 size_t block_size; 198 rc = block_get_bsize(dev_handle, &block_size); 199 if (rc != EOK) 200 goto end; 201 202 aoff64_t blocks; 203 rc = block_get_nblocks(dev_handle, &blocks); 204 if (rc != EOK) 205 goto end; 216 206 217 207 gpt_set_random_uuid(label->gpt->header->disk_guid); 218 208 219 209 /* Prepare the backup header */ 220 label->gpt->header->alternate_lba = label->gpt->header-> my_lba;221 label->gpt->header-> my_lba = host2uint64_t_le(n_blocks - 1);222 223 tmp= label->gpt->header->entry_lba;224 label->gpt->header->entry_lba = host2uint64_t_le( n_blocks -225 (uint32_t_le2host(label->gpt->header->fillries) * sizeof(gpt_entry_t))226 / b_size - 1);210 label->gpt->header->alternate_lba = label->gpt->header->current_lba; 211 label->gpt->header->current_lba = host2uint64_t_le(blocks - 1); 212 213 uint64_t lba = label->gpt->header->entry_lba; 214 label->gpt->header->entry_lba = host2uint64_t_le(blocks - 215 (uint32_t_le2host(label->gpt->header->fillries) * 216 sizeof(gpt_entry_t)) / block_size - 1); 227 217 228 218 label->gpt->header->header_crc32 = 0; 229 label->gpt->header->header_crc32 = host2uint32_t_le(230 compute_crc32((uint8_t *) label->gpt->header,231 uint32_t_le2host(label->gpt->header->header_size)));219 label->gpt->header->header_crc32 = 220 host2uint32_t_le(compute_crc32((uint8_t *) label->gpt->header, 221 uint32_t_le2host(label->gpt->header->header_size))); 232 222 233 223 /* Write to backup GPT header location */ 234 rc = block_write_direct(dev_handle, n_blocks - 1, GPT_HDR_BS, label->gpt->header); 235 if (rc != EOK) { 236 block_fini(dev_handle); 237 return rc; 238 } 239 224 rc = block_write_direct(dev_handle, blocks - 1, GPT_HDR_BS, 225 label->gpt->header); 226 if (rc != EOK) 227 goto end; 240 228 241 229 /* Prepare the main header */ 242 label->gpt->header->entry_lba = tmp;243 244 tmp= label->gpt->header->alternate_lba;245 label->gpt->header->alternate_lba = label->gpt->header-> my_lba;246 label->gpt->header-> my_lba = tmp;230 label->gpt->header->entry_lba = lba; 231 232 lba = label->gpt->header->alternate_lba; 233 label->gpt->header->alternate_lba = label->gpt->header->current_lba; 234 label->gpt->header->current_lba = lba; 247 235 248 236 label->gpt->header->header_crc32 = 0; 249 label->gpt->header->header_crc32 = host2uint32_t_le(250 compute_crc32((uint8_t *) label->gpt->header,251 uint32_t_le2host(label->gpt->header->header_size)));237 label->gpt->header->header_crc32 = 238 host2uint32_t_le(compute_crc32((uint8_t *) label->gpt->header, 239 uint32_t_le2host(label->gpt->header->header_size))); 252 240 253 241 /* Write to main GPT header location */ 254 rc = block_write_direct(dev_handle, GPT_HDR_BA, GPT_HDR_BS, label->gpt->header); 255 if (rc != EOK) 256 return rc; 242 rc = block_write_direct(dev_handle, GPT_HDR_BA, GPT_HDR_BS, 243 label->gpt->header); 244 if (rc != EOK) 245 goto end; 257 246 258 247 /* Write Protective MBR */ 259 248 br_block_t mbr; 260 249 memset(&mbr, 0, 512); 250 261 251 memset(mbr.pte[0].first_chs, 1, 3); 262 252 mbr.pte[0].ptype = 0xEE; 263 memset(mbr.pte[0].last_chs, 0x FF, 3);253 memset(mbr.pte[0].last_chs, 0xff, 3); 264 254 mbr.pte[0].first_lba = host2uint32_t_le(1); 265 mbr.pte[0].length = 0x FFFFFFFF;255 mbr.pte[0].length = 0xffffffff; 266 256 mbr.signature = host2uint16_t_le(BR_SIGNATURE); 267 257 268 258 rc = block_write_direct(dev_handle, 0, 1, &mbr); 259 260 end: 269 261 block_fini(dev_handle); 270 if (rc != EOK) 271 return rc; 272 273 return 0; 262 return rc; 274 263 } 275 264 276 265 /** Alloc partition array */ 277 gpt_partitions_t * gpt_alloc_partitions()266 gpt_partitions_t *gpt_alloc_partitions(void) 278 267 { 279 268 return alloc_part_array(GPT_MIN_PART_NUM); … … 281 270 282 271 /** Parse partitions from GPT 283 * @param label GPT label to be parsed 284 * 285 * @return EOK on success, errorcode otherwise 272 * 273 * @param label GPT label to be parsed. 274 * 275 * @return EOK on success, error code otherwise. 276 * 286 277 */ 287 278 int gpt_read_partitions(gpt_label_t *label) 288 279 { 289 int rc;290 unsigned int i;291 280 uint32_t fillries = uint32_t_le2host(label->gpt->header->fillries); 292 281 uint32_t ent_size = uint32_t_le2host(label->gpt->header->entry_size); … … 295 284 if (label->parts == NULL) { 296 285 label->parts = alloc_part_array(fillries); 297 if (label->parts == NULL) {286 if (label->parts == NULL) 298 287 return ENOMEM; 299 } 300 } 301 302 /* comm_size is ignored */ 303 rc = block_init(EXCHANGE_SERIALIZE, label->device, sizeof(gpt_entry_t)); 304 if (rc != EOK) 305 goto fail; 306 288 } 289 290 int rc = block_init(EXCHANGE_SERIALIZE, label->device, 291 sizeof(gpt_entry_t)); 292 if (rc != EOK) { 293 gpt_free_partitions(label->parts); 294 label->parts = NULL; 295 goto end; 296 } 297 307 298 size_t block_size; 308 299 rc = block_get_bsize(label->device, &block_size); 309 if (rc != EOK) 310 goto fini_fail; 311 300 if (rc != EOK) { 301 gpt_free_partitions(label->parts); 302 label->parts = NULL; 303 goto end; 304 } 305 312 306 aoff64_t pos = ent_lba * block_size; 313 314 /* 315 * Now we read just sizeof(gpt_entry_t) bytes for each entry from the device. 316 * Hopefully, this does not bypass cache (no mention in libblock.c), 317 * and also allows us to have variable partition entry size (but we 318 * will always read just sizeof(gpt_entry_t) bytes - hopefully they 319 * don't break backward compatibility) 320 */ 321 for (i = 0; i < fillries; ++i) { 322 /*FIXME: this does bypass cache... */ 323 rc = block_read_bytes_direct(label->device, pos, sizeof(gpt_entry_t), label->parts->part_array + i); 324 /* 325 * FIXME: but seqread() is just too complex... 326 * rc = block_seqread(gpt->device, &bufpos, &buflen, &pos, res->part_array[i], sizeof(gpt_entry_t)); 327 */ 307 308 for (uint32_t i = 0; i < fillries; i++) { 309 rc = block_read_bytes_direct(label->device, pos, sizeof(gpt_entry_t), 310 label->parts->part_array + i); 328 311 pos += ent_size; 329 330 if (rc != EOK) 331 goto fini_fail; 332 } 333 334 uint32_t crc = compute_crc32((uint8_t *) label->parts->part_array, 335 fillries * ent_size); 336 337 if (uint32_t_le2host(label->gpt->header->pe_array_crc32) != crc) 338 { 312 313 if (rc != EOK) { 314 gpt_free_partitions(label->parts); 315 label->parts = NULL; 316 goto end; 317 } 318 } 319 320 uint32_t crc = compute_crc32((uint8_t *) label->parts->part_array, 321 fillries * ent_size); 322 323 if (uint32_t_le2host(label->gpt->header->pe_array_crc32) != crc) { 339 324 rc = EBADCHECKSUM; 340 goto fini_fail; 341 } 342 325 gpt_free_partitions(label->parts); 326 label->parts = NULL; 327 goto end; 328 } 329 330 rc = EOK; 331 332 end: 343 333 block_fini(label->device); 344 return EOK;345 346 fini_fail:347 block_fini(label->device);348 349 fail:350 gpt_free_partitions(label->parts);351 label->parts = NULL;352 334 return rc; 353 335 } 354 336 355 337 /** Write GPT and partitions to device 356 * Note: also writes the header. 357 * @param label label to write 358 * @param dev_handle device to write the data to 359 * 360 * @return returns EOK on succes, errorcode otherwise 338 * 339 * Note: Also writes the header. 340 * 341 * @param label Label to write. 342 * @param dev_handle Device to write the data to. 343 * 344 * @return EOK on succes, error code otherwise 345 * 361 346 */ 362 347 int gpt_write_partitions(gpt_label_t *label, service_id_t dev_handle) 363 348 { 364 int rc;365 size_t b_size;366 367 349 /* comm_size of 4096 is ignored */ 368 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 4096);369 if ( rc != EOK && rc != EEXIST)350 int rc = block_init(EXCHANGE_ATOMIC, dev_handle, 4096); 351 if ((rc != EOK) && (rc != EEXIST)) 370 352 return rc; 371 353 372 rc = block_get_bsize(dev_handle, &b_size); 354 size_t block_size; 355 rc = block_get_bsize(dev_handle, &block_size); 373 356 if (rc != EOK) 374 357 goto fail; 375 358 376 aoff64_t n_blocks;377 rc = block_get_nblocks(dev_handle, & n_blocks);359 aoff64_t blocks; 360 rc = block_get_nblocks(dev_handle, &blocks); 378 361 if (rc != EOK) 379 362 goto fail; 380 363 381 /* When we're creating a new label from scratch, we need to fill 382 * the header with sensible defaults. */ 383 if (label->gpt == NULL) { 384 label->gpt = gpt_alloc_header(b_size); 385 } 386 387 uint32_t e_size = uint32_t_le2host(label->gpt->header->entry_size); 388 size_t fillries = label->parts->fill > GPT_MIN_PART_NUM ? label->parts->fill : GPT_MIN_PART_NUM; 389 390 if (e_size != sizeof(gpt_entry_t)) 364 if (label->gpt == NULL) 365 label->gpt = gpt_alloc_header(block_size); 366 367 uint32_t entry_size = 368 uint32_t_le2host(label->gpt->header->entry_size); 369 size_t fillries = (label->parts->fill > GPT_MIN_PART_NUM) ? 370 label->parts->fill : GPT_MIN_PART_NUM; 371 372 if (entry_size != sizeof(gpt_entry_t)) 391 373 return ENOTSUP; 392 374 393 375 label->gpt->header->fillries = host2uint32_t_le(fillries); 394 uint64_t arr_blocks = (fillries * sizeof(gpt_entry_t)) / b_size; 395 uint64_t gpt_space = arr_blocks + GPT_HDR_BS + 1; /* +1 for Protective MBR */ 376 377 uint64_t arr_blocks = (fillries * sizeof(gpt_entry_t)) / block_size; 378 379 /* Include Protective MBR */ 380 uint64_t gpt_space = arr_blocks + GPT_HDR_BS + 1; 381 396 382 label->gpt->header->first_usable_lba = host2uint64_t_le(gpt_space); 397 label->gpt->header->last_usable_lba = host2uint64_t_le(n_blocks - gpt_space - 1); 383 label->gpt->header->last_usable_lba = 384 host2uint64_t_le(blocks - gpt_space - 1); 398 385 399 386 /* Perform checks */ … … 402 389 continue; 403 390 404 if (!check_encaps(p, n_blocks, gpt_space)) {391 if (!check_encaps(p, blocks, gpt_space)) { 405 392 rc = ERANGE; 406 393 goto fail; … … 420 407 } 421 408 422 label->gpt->header->pe_array_crc32 = host2uint32_t_le(compute_crc32( 423 (uint8_t *) label->parts->part_array, 424 fillries * e_size)); 425 409 label->gpt->header->pe_array_crc32 = 410 host2uint32_t_le(compute_crc32((uint8_t *) label->parts->part_array, 411 fillries * entry_size)); 426 412 427 413 /* Write to backup GPT partition array location */ 428 rc = block_write_direct(dev_handle, n_blocks - arr_blocks - 1,429 arr_blocks, label->parts->part_array);414 rc = block_write_direct(dev_handle, blocks - arr_blocks - 1, 415 arr_blocks, label->parts->part_array); 430 416 if (rc != EOK) 431 417 goto fail; 432 418 433 419 /* Write to main GPT partition array location */ 434 rc = block_write_direct(dev_handle, uint64_t_le2host(label->gpt->header->entry_lba), 435 arr_blocks, label->parts->part_array); 420 rc = block_write_direct(dev_handle, 421 uint64_t_le2host(label->gpt->header->entry_lba), 422 arr_blocks, label->parts->part_array); 436 423 if (rc != EOK) 437 424 goto fail; … … 444 431 } 445 432 446 /** Alloc new partition 447 * 448 * @return returns pointer to the new partition or NULL 449 * 450 * Note: use either gpt_alloc_partition or gpt_get_partition. 433 /** Allocate a new partition 434 * 435 * Note: Use either gpt_alloc_partition() or gpt_get_partition(). 451 436 * This returns a memory block (zero-filled) and needs gpt_add_partition() 452 437 * to be called to insert it into a partition array. 453 438 * Requires you to call gpt_free_partition afterwards. 454 */ 455 gpt_part_t * gpt_alloc_partition(void) 456 { 457 gpt_part_t *p = malloc(sizeof(gpt_part_t)); 458 if (p == NULL) 439 * 440 * @return Pointer to the new partition or NULL. 441 * 442 */ 443 gpt_part_t *gpt_alloc_partition(void) 444 { 445 gpt_part_t *partition = malloc(sizeof(gpt_part_t)); 446 if (partition == NULL) 459 447 return NULL; 460 448 461 memset(p, 0, sizeof(gpt_part_t)); 462 463 return p; 464 } 465 466 /** Alloc new partition already inside the label 467 * 468 * @param label label to carry new partition 469 * 470 * @return returns pointer to the new partition or NULL on ENOMEM 471 * 472 * Note: use either gpt_alloc_partition or gpt_get_partition. 449 memset(partition, 0, sizeof(gpt_part_t)); 450 451 return partition; 452 } 453 454 /** Allocate a new partition already inside the label 455 * 456 * Note: Use either gpt_alloc_partition() or gpt_get_partition(). 473 457 * This one returns a pointer to the first empty structure already 474 458 * inside the array, so don't call gpt_add_partition() afterwards. 475 459 * This is the one you will usually want. 476 */ 477 gpt_part_t * gpt_get_partition(gpt_label_t *label) 478 { 479 gpt_part_t *p; 480 460 * 461 * @param label Label to carry new partition. 462 * 463 * @return Pointer to the new partition or NULL. 464 * 465 */ 466 gpt_part_t *gpt_get_partition(gpt_label_t *label) 467 { 468 gpt_part_t *partition; 481 469 482 470 /* Find the first empty entry */ … … 487 475 } 488 476 489 p = label->parts->part_array + label->parts->fill++; 490 491 } while (gpt_get_part_type(p) != GPT_PTE_UNUSED); 492 493 return p; 477 partition = label->parts->part_array + label->parts->fill++; 478 } while (gpt_get_part_type(partition) != GPT_PTE_UNUSED); 479 480 return partition; 494 481 } 495 482 496 483 /** Get partition already inside the label 497 484 * 498 * @param label label to carrying the partition 499 * @param idx index of the partition 500 * 501 * @return returns pointer to the partition 502 * or NULL when out of range 503 * 504 * Note: For new partitions use either gpt_alloc_partition or 505 * gpt_get_partition unless you want a partition at a specific place. 485 * Note: For new partitions use either gpt_alloc_partition() or 486 * gpt_get_partition() unless you want a partition at a specific place. 506 487 * This returns a pointer to a structure already inside the array, 507 488 * so don't call gpt_add_partition() afterwards. … … 510 491 * for indexes smaller than either 128 or the actual number of filled 511 492 * entries. 512 */ 513 gpt_part_t * gpt_get_partition_at(gpt_label_t *label, size_t idx) 514 { 515 return NULL; 516 517 if (idx >= GPT_MIN_PART_NUM && idx >= label->parts->fill) 493 * 494 * @param label Label to carrying the partition. 495 * @param idx Index of the partition. 496 * 497 * @return Pointer to the partition or NULL when out of range. 498 * 499 */ 500 gpt_part_t *gpt_get_partition_at(gpt_label_t *label, size_t idx) 501 { 502 if ((idx >= GPT_MIN_PART_NUM) && (idx >= label->parts->fill)) 518 503 return NULL; 519 504 … … 523 508 /** Copy partition into partition array 524 509 * 525 * @param parts target label 526 * @param partition source partition to copy 527 * 528 * @return -1 on error, 0 otherwise 529 * 530 * Note: for use with gpt_alloc_partition() only. You will get 510 * Note: For use with gpt_alloc_partition() only. You will get 531 511 * duplicates with gpt_get_partition(). 532 * Note: does not call gpt_free_partition()! 512 * Note: Does not call gpt_free_partition()! 513 * 514 * @param parts Target label 515 * @param partition Source partition to copy 516 * 517 * @return EOK on succes, error code otherwise 518 * 533 519 */ 534 520 int gpt_add_partition(gpt_label_t *label, gpt_part_t *partition) 535 521 { 536 gpt_part_t *p;537 522 /* Find the first empty entry */ 523 524 gpt_part_t *part; 525 538 526 do { 539 527 if (label->parts->fill == label->parts->arr_size) { … … 542 530 } 543 531 544 p = label->parts->part_array + label->parts->fill++; 545 546 } while (gpt_get_part_type(p) != GPT_PTE_UNUSED); 547 548 549 memcpy(p, partition, sizeof(gpt_entry_t)); 550 551 532 part = label->parts->part_array + label->parts->fill++; 533 } while (gpt_get_part_type(part) != GPT_PTE_UNUSED); 534 535 memcpy(part, partition, sizeof(gpt_entry_t)); 552 536 return EOK; 553 537 } 554 538 555 539 /** Remove partition from array 556 * @param label label to remove from 557 * @param idx index of the partition to remove 558 * 559 * @return EOK on success, ENOMEM on array reduction failure 560 * 561 * Note: even if it fails, the partition still gets removed. Only 540 * 541 * Note: Even if it fails, the partition still gets removed. Only 562 542 * reducing the array failed. 543 * 544 * @param label Label to remove from 545 * @param idx Index of the partition to remove 546 * 547 * @return EOK on success, ENOMEM on array reduction failure 548 * 563 549 */ 564 550 int gpt_remove_partition(gpt_label_t *label, size_t idx) … … 567 553 return EINVAL; 568 554 569 /* 570 * FIXME !555 /* 556 * FIXME: 571 557 * If we allow blank spots, we break the array. If we have more than 572 558 * 128 partitions in the array and then remove something from 573 559 * the first 128 partitions, we would forget to write the last one. 574 560 */ 561 575 562 memset(label->parts->part_array + idx, 0, sizeof(gpt_entry_t)); 576 563 … … 578 565 label->parts->fill = idx; 579 566 580 /* 581 * FIXME! HOPEFULLY FIXED. 582 * We cannot reduce the array so simply. We may have some partitions 583 * there since we allow blank spots. 584 */ 585 gpt_part_t * p; 586 587 if (label->parts->fill > GPT_MIN_PART_NUM && 588 label->parts->fill < (label->parts->arr_size / 2) - GPT_IGNORE_FILL_NUM) { 589 for (p = gpt_get_partition_at(label, label->parts->arr_size / 2); 590 p < label->parts->part_array + label->parts->arr_size; ++p) { 591 if (gpt_get_part_type(p) != GPT_PTE_UNUSED) 592 return EOK; 567 gpt_part_t *partition; 568 569 if ((label->parts->fill > GPT_MIN_PART_NUM) && 570 (label->parts->fill < (label->parts->arr_size / 2) - 571 GPT_IGNORE_FILL_NUM)) { 572 for (partition = gpt_get_partition_at(label, label->parts->arr_size / 2); 573 partition < label->parts->part_array + label->parts->arr_size; 574 partition++) { 575 if (gpt_get_part_type(partition) != GPT_PTE_UNUSED) 576 return EOK; 593 577 } 594 578 … … 596 580 return ENOMEM; 597 581 } 598 582 599 583 return EOK; 600 584 } … … 602 586 /** Free partition list 603 587 * 604 * @param parts partition list to be freed 605 */ 606 void gpt_free_partitions(gpt_partitions_t * parts) 588 * @param parts Partition list to be freed 589 * 590 */ 591 void gpt_free_partitions(gpt_partitions_t *parts) 607 592 { 608 593 free(parts->part_array); … … 610 595 } 611 596 612 /** Get partition type by linear search 613 * (hopefully this doesn't get slow) 614 */ 615 size_t gpt_get_part_type(gpt_part_t * p) 597 /** Get partition type */ 598 size_t gpt_get_part_type(gpt_part_t *partition) 616 599 { 617 600 size_t i; 618 601 619 602 for (i = 0; gpt_ptypes[i].guid != NULL; i++) { 620 if (p->part_type[3] == get_byte(gpt_ptypes[i].guid +0) && 621 p->part_type[2] == get_byte(gpt_ptypes[i].guid +2) && 622 p->part_type[1] == get_byte(gpt_ptypes[i].guid +4) && 623 p->part_type[0] == get_byte(gpt_ptypes[i].guid +6) && 624 625 p->part_type[5] == get_byte(gpt_ptypes[i].guid +8) && 626 p->part_type[4] == get_byte(gpt_ptypes[i].guid +10) && 627 628 p->part_type[7] == get_byte(gpt_ptypes[i].guid +12) && 629 p->part_type[6] == get_byte(gpt_ptypes[i].guid +14) && 630 631 p->part_type[8] == get_byte(gpt_ptypes[i].guid +16) && 632 p->part_type[9] == get_byte(gpt_ptypes[i].guid +18) && 633 p->part_type[10] == get_byte(gpt_ptypes[i].guid +20) && 634 p->part_type[11] == get_byte(gpt_ptypes[i].guid +22) && 635 p->part_type[12] == get_byte(gpt_ptypes[i].guid +24) && 636 p->part_type[13] == get_byte(gpt_ptypes[i].guid +26) && 637 p->part_type[14] == get_byte(gpt_ptypes[i].guid +28) && 638 p->part_type[15] == get_byte(gpt_ptypes[i].guid +30)) 639 break; 603 if ((partition->part_type[3] == get_byte(gpt_ptypes[i].guid + 0)) && 604 (partition->part_type[2] == get_byte(gpt_ptypes[i].guid + 2)) && 605 (partition->part_type[1] == get_byte(gpt_ptypes[i].guid + 4)) && 606 (partition->part_type[0] == get_byte(gpt_ptypes[i].guid + 6)) && 607 (partition->part_type[5] == get_byte(gpt_ptypes[i].guid + 8)) && 608 (partition->part_type[4] == get_byte(gpt_ptypes[i].guid + 10)) && 609 (partition->part_type[7] == get_byte(gpt_ptypes[i].guid + 12)) && 610 (partition->part_type[6] == get_byte(gpt_ptypes[i].guid + 14)) && 611 (partition->part_type[8] == get_byte(gpt_ptypes[i].guid + 16)) && 612 (partition->part_type[9] == get_byte(gpt_ptypes[i].guid + 18)) && 613 (partition->part_type[10] == get_byte(gpt_ptypes[i].guid + 20)) && 614 (partition->part_type[11] == get_byte(gpt_ptypes[i].guid + 22)) && 615 (partition->part_type[12] == get_byte(gpt_ptypes[i].guid + 24)) && 616 (partition->part_type[13] == get_byte(gpt_ptypes[i].guid + 26)) && 617 (partition->part_type[14] == get_byte(gpt_ptypes[i].guid + 28)) && 618 (partition->part_type[15] == get_byte(gpt_ptypes[i].guid + 30))) 619 return i; 640 620 } 641 621 … … 643 623 } 644 624 645 /** Set partition type 646 * @param p partition to be set 647 * @param type partition type to set 648 * - see our fine selection at gpt_ptypes to choose from 649 */ 650 void gpt_set_part_type(gpt_part_t * p, size_t type) 625 /** Set partition type */ 626 void gpt_set_part_type(gpt_part_t *partition, size_t type) 651 627 { 652 628 /* Beware: first 3 blocks are byteswapped! */ 653 p ->part_type[3] = get_byte(gpt_ptypes[type].guid +0);654 p ->part_type[2] = get_byte(gpt_ptypes[type].guid +2);655 p ->part_type[1] = get_byte(gpt_ptypes[type].guid +4);656 p ->part_type[0] = get_byte(gpt_ptypes[type].guid +6);657 658 p ->part_type[5] = get_byte(gpt_ptypes[type].guid +8);659 p ->part_type[4] = get_byte(gpt_ptypes[type].guid +10);660 661 p ->part_type[7] = get_byte(gpt_ptypes[type].guid +12);662 p ->part_type[6] = get_byte(gpt_ptypes[type].guid +14);663 664 p ->part_type[8] = get_byte(gpt_ptypes[type].guid +16);665 p ->part_type[9] = get_byte(gpt_ptypes[type].guid +18);666 p ->part_type[10] = get_byte(gpt_ptypes[type].guid +20);667 p ->part_type[11] = get_byte(gpt_ptypes[type].guid +22);668 p ->part_type[12] = get_byte(gpt_ptypes[type].guid +24);669 p ->part_type[13] = get_byte(gpt_ptypes[type].guid +26);670 p ->part_type[14] = get_byte(gpt_ptypes[type].guid +28);671 p ->part_type[15] = get_byte(gpt_ptypes[type].guid +30);629 partition->part_type[3] = get_byte(gpt_ptypes[type].guid + 0); 630 partition->part_type[2] = get_byte(gpt_ptypes[type].guid + 2); 631 partition->part_type[1] = get_byte(gpt_ptypes[type].guid + 4); 632 partition->part_type[0] = get_byte(gpt_ptypes[type].guid + 6); 633 634 partition->part_type[5] = get_byte(gpt_ptypes[type].guid + 8); 635 partition->part_type[4] = get_byte(gpt_ptypes[type].guid + 10); 636 637 partition->part_type[7] = get_byte(gpt_ptypes[type].guid + 12); 638 partition->part_type[6] = get_byte(gpt_ptypes[type].guid + 14); 639 640 partition->part_type[8] = get_byte(gpt_ptypes[type].guid + 16); 641 partition->part_type[9] = get_byte(gpt_ptypes[type].guid + 18); 642 partition->part_type[10] = get_byte(gpt_ptypes[type].guid + 20); 643 partition->part_type[11] = get_byte(gpt_ptypes[type].guid + 22); 644 partition->part_type[12] = get_byte(gpt_ptypes[type].guid + 24); 645 partition->part_type[13] = get_byte(gpt_ptypes[type].guid + 26); 646 partition->part_type[14] = get_byte(gpt_ptypes[type].guid + 28); 647 partition->part_type[15] = get_byte(gpt_ptypes[type].guid + 30); 672 648 } 673 649 674 650 /** Get partition starting LBA */ 675 uint64_t gpt_get_start_lba(gpt_part_t * p)676 { 677 return uint64_t_le2host(p ->start_lba);651 uint64_t gpt_get_start_lba(gpt_part_t *partition) 652 { 653 return uint64_t_le2host(partition->start_lba); 678 654 } 679 655 680 656 /** Set partition starting LBA */ 681 void gpt_set_start_lba(gpt_part_t * p, uint64_t start)682 { 683 p ->start_lba = host2uint64_t_le(start);657 void gpt_set_start_lba(gpt_part_t *partition, uint64_t start) 658 { 659 partition->start_lba = host2uint64_t_le(start); 684 660 } 685 661 686 662 /** Get partition ending LBA */ 687 uint64_t gpt_get_end_lba(gpt_part_t * p)688 { 689 return uint64_t_le2host(p ->end_lba);663 uint64_t gpt_get_end_lba(gpt_part_t *partition) 664 { 665 return uint64_t_le2host(partition->end_lba); 690 666 } 691 667 692 668 /** Set partition ending LBA */ 693 void gpt_set_end_lba(gpt_part_t * p, uint64_t end)694 { 695 p ->end_lba = host2uint64_t_le(end);669 void gpt_set_end_lba(gpt_part_t *partition, uint64_t end) 670 { 671 partition->end_lba = host2uint64_t_le(end); 696 672 } 697 673 698 674 /** Get partition name */ 699 unsigned char * gpt_get_part_name(gpt_part_t * p)700 { 701 return p ->part_name;675 unsigned char * gpt_get_part_name(gpt_part_t *partition) 676 { 677 return partition->part_name; 702 678 } 703 679 704 680 /** Copy partition name */ 705 void gpt_set_part_name(gpt_part_t *p , char *name, size_t length)681 void gpt_set_part_name(gpt_part_t *partition, char *name, size_t length) 706 682 { 707 683 if (length >= 72) 708 684 length = 71; 709 710 memcpy(p ->part_name, name, length);711 p ->part_name[length] = '\0';685 686 memcpy(partition->part_name, name, length); 687 partition->part_name[length] = '\0'; 712 688 } 713 689 714 690 /** Get partition attribute */ 715 bool gpt_get_flag(gpt_part_t * p, GPT_ATTRflag)716 { 717 return (p ->attributes & (((uint64_t) 1) << flag)) ? 1 : 0;691 bool gpt_get_flag(gpt_part_t *partition, gpt_attr_t flag) 692 { 693 return (partition->attributes & (((uint64_t) 1) << flag)) ? 1 : 0; 718 694 } 719 695 720 696 /** Set partition attribute */ 721 void gpt_set_flag(gpt_part_t * p, GPT_ATTRflag, bool value)722 { 723 uint64_t attr = p ->attributes;724 697 void gpt_set_flag(gpt_part_t *partition, gpt_attr_t flag, bool value) 698 { 699 uint64_t attr = partition->attributes; 700 725 701 if (value) 726 702 attr = attr | (((uint64_t) 1) << flag); 727 703 else 728 704 attr = attr ^ (attr & (((uint64_t) 1) << flag)); 729 730 p ->attributes = attr;705 706 partition->attributes = attr; 731 707 } 732 708 733 709 /** Generate a new pseudo-random UUID 734 * @param uuid Pointer to the UUID to overwrite. 735 */ 736 void gpt_set_random_uuid(uint8_t * uuid) 710 * 711 * FIXME: This UUID generator is not compliant with RFC 4122. 712 * 713 */ 714 void gpt_set_random_uuid(uint8_t *uuid) 737 715 { 738 716 srandom((unsigned int) (size_t) uuid); 739 717 740 unsigned int i; 741 for (i = 0; i < 16/sizeof(long int); ++i) 742 ((long int *)uuid)[i] = random(); 743 718 for (size_t i = 0; i < 16; i++) 719 uuid[i] = random(); 744 720 } 745 721 … … 747 723 uint64_t gpt_get_next_aligned(uint64_t addr, unsigned int alignment) 748 724 { 749 uint64_t div = addr / alignment; 750 return (div + 1) * alignment; 751 } 752 753 /* Internal functions follow */ 754 755 static int load_and_check_header(service_id_t dev_handle, aoff64_t addr, size_t b_size, gpt_header_t * header) 756 { 757 int rc; 758 759 rc = block_read_direct(dev_handle, addr, GPT_HDR_BS, header); 725 return ALIGN_UP(addr + 1, alignment); 726 } 727 728 static int load_and_check_header(service_id_t dev_handle, aoff64_t addr, 729 size_t block_size, gpt_header_t *header) 730 { 731 int rc = block_read_direct(dev_handle, addr, GPT_HDR_BS, header); 760 732 if (rc != EOK) 761 733 return rc; 762 763 unsigned int i; 734 764 735 /* Check the EFI signature */ 765 for ( i = 0; i < 8; ++i) {736 for (unsigned int i = 0; i < 8; i++) { 766 737 if (header->efi_signature[i] != efi_signature[i]) 767 738 return EINVAL; 768 739 } 769 740 770 741 /* Check the CRC32 of the header */ 771 742 uint32_t crc = header->header_crc32; 772 743 header->header_crc32 = 0; 744 773 745 if (crc != compute_crc32((uint8_t *) header, header->header_size)) 774 746 return EBADCHECKSUM; 775 747 else 776 748 header->header_crc32 = crc; 777 749 778 750 /* Check for zeroes in the rest of the block */ 779 for ( i = sizeof(gpt_header_t); i < b_size; ++i) {751 for (size_t i = sizeof(gpt_header_t); i < block_size; i++) { 780 752 if (((uint8_t *) header)[i] != 0) 781 753 return EINVAL; 782 754 } 783 755 784 756 return EOK; 785 757 } 786 758 787 static gpt_partitions_t * alloc_part_array(uint32_t num) 788 { 789 gpt_partitions_t * res = malloc(sizeof(gpt_partitions_t)); 790 if (res == NULL) { 791 errno = ENOMEM; 759 static gpt_partitions_t *alloc_part_array(uint32_t num) 760 { 761 gpt_partitions_t *res = malloc(sizeof(gpt_partitions_t)); 762 if (res == NULL) 792 763 return NULL; 793 }794 764 795 765 uint32_t size = num > GPT_BASE_PART_NUM ? num : GPT_BASE_PART_NUM; … … 797 767 if (res->part_array == NULL) { 798 768 free(res); 799 errno = ENOMEM;800 769 return NULL; 801 770 } … … 805 774 res->fill = 0; 806 775 res->arr_size = num; 807 776 808 777 return res; 809 778 } 810 779 811 static int extend_part_array(gpt_partitions_t * p)812 { 813 size_t nsize = p ->arr_size * 2;814 gpt_entry_t * tmp= malloc(nsize * sizeof(gpt_entry_t));815 if ( tmp == NULL) {816 errno =ENOMEM;817 return -1;818 }819 820 memcpy(tmp, p->part_array, p->fill * sizeof(gpt_entry_t));821 free(p->part_array);822 p ->part_array = tmp;823 p ->arr_size = nsize;824 825 return 0;826 } 827 828 static int reduce_part_array(gpt_partitions_t * p)829 { 830 if (p ->arr_size > GPT_MIN_PART_NUM) {831 unsigned int nsize = p ->arr_size / 2;780 static int extend_part_array(gpt_partitions_t *partition) 781 { 782 size_t nsize = partition->arr_size * 2; 783 gpt_entry_t *entry = malloc(nsize * sizeof(gpt_entry_t)); 784 if (entry == NULL) 785 return ENOMEM; 786 787 memcpy(entry, partition->part_array, partition->fill * 788 sizeof(gpt_entry_t)); 789 free(partition->part_array); 790 791 partition->part_array = entry; 792 partition->arr_size = nsize; 793 794 return EOK; 795 } 796 797 static int reduce_part_array(gpt_partitions_t *partition) 798 { 799 if (partition->arr_size > GPT_MIN_PART_NUM) { 800 unsigned int nsize = partition->arr_size / 2; 832 801 nsize = nsize > GPT_MIN_PART_NUM ? nsize : GPT_MIN_PART_NUM; 833 gpt_entry_t * tmp = malloc(nsize * sizeof(gpt_entry_t)); 834 if (tmp == NULL) 802 803 gpt_entry_t *entry = malloc(nsize * sizeof(gpt_entry_t)); 804 if (entry == NULL) 835 805 return ENOMEM; 836 837 memcpy( tmp, p->part_array, p->fill < nsize ? p->fill : nsize);838 free(p->part_array);839 p->part_array = tmp;840 p->arr_size = nsize;841 }842 843 return 0;844 } 845 846 /* Parse a byte from a string in hexadecimal 847 * i.e., "FF" => 255 848 */849 static uint8_t get_byte(const char * c)806 807 memcpy(entry, partition->part_array, 808 partition->fill < nsize ? partition->fill : nsize); 809 free(partition->part_array); 810 811 partition->part_array = entry; 812 partition->arr_size = nsize; 813 } 814 815 return EOK; 816 } 817 818 /* Parse a byte from a string in hexadecimal */ 819 static uint8_t get_byte(const char *c) 850 820 { 851 821 uint8_t val = 0; 852 char hex[3] = {*c, *(c +1), 0};853 854 errno =str_uint8_t(hex, NULL, 16, false, &val);822 char hex[3] = {*c, *(c + 1), 0}; 823 824 str_uint8_t(hex, NULL, 16, false, &val); 855 825 return val; 856 826 } 857 827 858 static bool check_overlap(gpt_part_t * p1, gpt_part_t * p2) 859 { 860 if (gpt_get_start_lba(p1) < gpt_get_start_lba(p2) && gpt_get_end_lba(p1) < gpt_get_start_lba(p2)) { 828 static bool check_overlap(gpt_part_t *part1, gpt_part_t *part2) 829 { 830 if ((gpt_get_start_lba(part1) < gpt_get_start_lba(part2)) && 831 (gpt_get_end_lba(part1) < gpt_get_start_lba(part2))) 861 832 return false; 862 } else if (gpt_get_start_lba(p1) > gpt_get_start_lba(p2) && gpt_get_end_lba(p2) < gpt_get_start_lba(p1)) { 833 834 if ((gpt_get_start_lba(part1) > gpt_get_start_lba(part2)) && 835 (gpt_get_end_lba(part2) < gpt_get_start_lba(part1))) 863 836 return false; 864 } 865 837 866 838 return true; 867 839 } 868 840 869 static bool check_encaps(gpt_part_t *p, uint64_t n_blocks, uint64_t first_lba) 870 { 871 /* 872 * We allow "<=" in the second expression because it lacks MBR so 873 * it's by 1 block smaller. 841 static bool check_encaps(gpt_part_t *part, uint64_t blocks, 842 uint64_t first_lba) 843 { 844 /* 845 * We allow "<=" in the second expression because it lacks 846 * MBR so it is smaller by 1 block. 874 847 */ 875 if (gpt_get_start_lba(p) >= first_lba && gpt_get_end_lba(p) <= n_blocks - first_lba) 848 if ((gpt_get_start_lba(part) >= first_lba) && 849 (gpt_get_end_lba(part) <= blocks - first_lba)) 876 850 return true; 877 851 -
uspace/lib/gpt/libgpt.h
rd51beba3 r6453e306 1 1 /* 2 2 * Copyright (c) 2009 Jiri Svoboda 3 * Copyright (c) 2011 , 2012,2013 Dominik Taborsky3 * Copyright (c) 2011-2013 Dominik Taborsky 4 4 * All rights reserved. 5 5 * … … 37 37 #define LIBGPT_LIBGPT_H_ 38 38 39 #define LIBGPT_NAME "libgpt"40 41 39 #include <loc.h> 42 40 #include <sys/types.h> 43 44 41 #include "gpt.h" 45 42 46 43 /** Block address of GPT header. */ 47 #define GPT_HDR_BA 1 44 #define GPT_HDR_BA 1 45 48 46 /** Block size of GPT header. */ 49 #define GPT_HDR_BS 1 47 #define GPT_HDR_BS 1 48 50 49 /** Minimum number of GPT partition entries */ 51 #define GPT_MIN_PART_NUM 128 50 #define GPT_MIN_PART_NUM 128 51 52 52 /** Basic number of GPT partition entries */ 53 #define GPT_BASE_PART_NUM (GPT_MIN_PART_NUM) 53 #define GPT_BASE_PART_NUM (GPT_MIN_PART_NUM) 54 54 55 /** How much fill we ignore before resizing partition array */ 55 #define GPT_IGNORE_FILL_NUM 1056 #define GPT_IGNORE_FILL_NUM 10 56 57 57 58 /** Unused partition entry */ 58 #define GPT_PTE_UNUSED 0 59 #define GPT_PTE_UNUSED 0 60 61 /** Raw GPT header. 62 * 63 * Uses more bytes than sizeof(gpt_header_t). 64 */ 65 typedef struct { 66 gpt_header_t *header; 67 } gpt_t; 68 69 typedef gpt_entry_t gpt_part_t; 70 71 typedef struct { 72 /** Number of entries */ 73 size_t fill; 74 75 /** Size of the array */ 76 size_t arr_size; 77 78 /** Resizable partition array */ 79 gpt_part_t *part_array; 80 } gpt_partitions_t; 81 82 typedef struct { 83 gpt_t *gpt; 84 gpt_partitions_t *parts; 85 service_id_t device; 86 } gpt_label_t; 87 88 typedef struct { 89 const char *desc; 90 const char *guid; 91 } partition_type_t; 59 92 60 93 /** GPT header signature ("EFI PART" in ASCII) */ … … 62 95 extern const uint8_t revision[4]; 63 96 64 typedef struct { 65 /** Raw header. Has more bytes alloced than sizeof(gpt_header_t)! 66 * See gpt_alloc_header() to know why. */ 67 gpt_header_t *header; 68 } gpt_t; 97 extern const partition_type_t gpt_ptypes[]; 69 98 70 typedef gpt_entry_t gpt_part_t; 71 72 typedef struct gpt_parts { 73 /** Number of entries */ 74 size_t fill; 75 /** Size of the array */ 76 size_t arr_size; 77 /** Resizable partition array */ 78 gpt_entry_t *part_array; 79 } gpt_partitions_t; 80 81 82 typedef struct gpt_table { 83 gpt_t *gpt; 84 gpt_partitions_t *parts; 85 service_id_t device; 86 } gpt_label_t; 87 88 struct partition_type { 89 const char *desc; 90 const char *guid; 91 }; 92 93 extern const struct partition_type gpt_ptypes[]; 94 95 extern gpt_label_t * gpt_alloc_label(void); 99 extern gpt_label_t *gpt_alloc_label(void); 96 100 extern void gpt_free_label(gpt_label_t *); 97 101 98 extern gpt_t * gpt_alloc_header(size_t);99 extern int gpt_read_header(gpt_label_t *, service_id_t);100 extern int gpt_write_header(gpt_label_t *, service_id_t);102 extern gpt_t *gpt_alloc_header(size_t); 103 extern int gpt_read_header(gpt_label_t *, service_id_t); 104 extern int gpt_write_header(gpt_label_t *, service_id_t); 101 105 102 extern gpt_partitions_t * gpt_alloc_partitions(void);103 extern int gpt_read_partitions(gpt_label_t *);104 extern int gpt_write_partitions(gpt_label_t *, service_id_t);105 extern gpt_part_t * gpt_alloc_partition(void);106 extern gpt_part_t * gpt_get_partition(gpt_label_t *);107 extern gpt_part_t * gpt_get_partition_at(gpt_label_t *, size_t);108 extern int gpt_add_partition(gpt_label_t *, gpt_part_t *);109 extern int gpt_remove_partition(gpt_label_t *, size_t);106 extern gpt_partitions_t *gpt_alloc_partitions(void); 107 extern int gpt_read_partitions(gpt_label_t *); 108 extern int gpt_write_partitions(gpt_label_t *, service_id_t); 109 extern gpt_part_t *gpt_alloc_partition(void); 110 extern gpt_part_t *gpt_get_partition(gpt_label_t *); 111 extern gpt_part_t *gpt_get_partition_at(gpt_label_t *, size_t); 112 extern int gpt_add_partition(gpt_label_t *, gpt_part_t *); 113 extern int gpt_remove_partition(gpt_label_t *, size_t); 110 114 111 extern size_t gpt_get_part_type(gpt_part_t *);112 extern void gpt_set_part_type(gpt_part_t *, size_t);113 extern void gpt_set_start_lba(gpt_part_t *, uint64_t);114 extern uint64_t gpt_get_start_lba(gpt_part_t *);115 extern void gpt_set_end_lba(gpt_part_t *, uint64_t);116 extern uint64_t gpt_get_end_lba(gpt_part_t *);117 extern unsigned char * gpt_get_part_name(gpt_part_t *);118 extern void gpt_set_part_name(gpt_part_t *, char *, size_t);119 extern bool gpt_get_flag (gpt_part_t *, GPT_ATTR);120 extern void gpt_set_flag (gpt_part_t *, GPT_ATTR, bool);115 extern size_t gpt_get_part_type(gpt_part_t *); 116 extern void gpt_set_part_type(gpt_part_t *, size_t); 117 extern void gpt_set_start_lba(gpt_part_t *, uint64_t); 118 extern uint64_t gpt_get_start_lba(gpt_part_t *); 119 extern void gpt_set_end_lba(gpt_part_t *, uint64_t); 120 extern uint64_t gpt_get_end_lba(gpt_part_t *); 121 extern unsigned char *gpt_get_part_name(gpt_part_t *); 122 extern void gpt_set_part_name(gpt_part_t *, char *, size_t); 123 extern bool gpt_get_flag(gpt_part_t *, gpt_attr_t); 124 extern void gpt_set_flag(gpt_part_t *, gpt_attr_t, bool); 121 125 122 extern void gpt_set_random_uuid(uint8_t *);123 extern uint64_t gpt_get_next_aligned(uint64_t, unsigned int);126 extern void gpt_set_random_uuid(uint8_t *); 127 extern uint64_t gpt_get_next_aligned(uint64_t, unsigned int); 124 128 125 129 126 130 #define gpt_part_foreach(label, iterator) \ 127 for(gpt_part_t * iterator = (label)->parts->part_array; \ 128 iterator < (label)->parts->part_array + (label)->parts->arr_size; ++iterator) 131 for (gpt_part_t *iterator = (label)->parts->part_array; \ 132 iterator < (label)->parts->part_array + (label)->parts->arr_size; \ 133 iterator++) 129 134 130 135 extern void gpt_free_gpt(gpt_t *); … … 132 137 133 138 #endif 134
Note:
See TracChangeset
for help on using the changeset viewer.
