Changeset 6453e306 in mainline for uspace/lib
- 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
- Files:
-
- 8 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 52 uint8_t 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 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 * 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 * 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 * 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 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 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 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 * 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 * 99 extern int 100 extern int 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 * 103 extern int gpt_read_partitions(gpt_label_t *);104 extern int 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 * 108 extern int gpt_add_partition(gpt_label_t *, gpt_part_t *);109 extern int 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 112 extern void 113 extern void 114 extern uint64_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 * 118 extern void 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 123 extern uint64_t 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 -
uspace/lib/mbr/Makefile
rd51beba3 r6453e306 28 28 29 29 USPACE_PREFIX = ../.. 30 EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -DDEBUG_CONFIG30 EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) 31 31 LIBRARY = libmbr 32 32 -
uspace/lib/mbr/libmbr.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 * … … 27 27 */ 28 28 29 29 /** @addtogroup libmbr 30 30 * @{ 31 31 */ … … 43 43 #include <stdlib.h> 44 44 #include <str_error.h> 45 45 #include <align.h> 46 46 #include "libmbr.h" 47 47 48 static br_block_t * 48 static br_block_t *alloc_br(void); 49 49 static int decode_part(pt_entry_t *, mbr_part_t *, uint32_t); 50 50 static int decode_logical(mbr_label_t *, mbr_part_t *); … … 57 57 58 58 /** Allocate and initialize mbr_label_t structure */ 59 mbr_label_t * 59 mbr_label_t *mbr_alloc_label(void) 60 60 { 61 61 mbr_label_t *label = malloc(sizeof(mbr_label_t)); … … 88 88 89 89 /** Allocate memory for mbr_t */ 90 mbr_t * 90 mbr_t *mbr_alloc_mbr(void) 91 91 { 92 92 return malloc(sizeof(mbr_t)); … … 94 94 95 95 /** Read MBR from specific device 96 * @param label label to write data to 97 * @param dev_handle device to read MBR from 98 * 99 * @return EOK on success, error code on error 96 * 97 * @param label Label to be read. 98 * @param dev_handle Device to read MBR from. 99 * 100 * @return EOK on success, error code on error. 101 * 100 102 */ 101 103 int mbr_read_mbr(mbr_label_t *label, service_id_t dev_handle) 102 104 { 103 int rc;104 105 105 if (label->mbr == NULL) { 106 106 label->mbr = mbr_alloc_mbr(); 107 if (label->mbr == NULL) {107 if (label->mbr == NULL) 108 108 return ENOMEM; 109 } 110 } 111 112 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 109 } 110 111 int rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 113 112 if (rc != EOK) 114 113 return rc; 115 116 rc = block_read_direct(dev_handle, 0, 1, & (label->mbr->raw_data));114 115 rc = block_read_direct(dev_handle, 0, 1, &label->mbr->raw_data); 117 116 block_fini(dev_handle); 118 117 if (rc != EOK) 119 118 return rc; 120 119 121 120 label->device = dev_handle; 122 121 123 122 return EOK; 124 123 } 125 124 126 /** Write mbr to disk 127 * @param label MBR to be written 128 * @param dev_handle device handle to write MBR to (may be different 129 * from the device in 'mbr') 130 * 131 * @return 0 on success, otherwise libblock error code 125 /** Write MBR to specific device 126 * 127 * @param label Label to be written. 128 * @param dev_handle Device to write MBR to. 129 * 130 * @return EOK on success, error code on error. 131 * 132 132 */ 133 133 int mbr_write_mbr(mbr_label_t *label, service_id_t dev_handle) 134 134 { 135 int rc; 136 137 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 138 if (rc != EOK) { 135 int rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 136 if (rc != EOK) 139 137 return rc; 140 } 141 142 rc = block_write_direct(dev_handle, 0, 1, &(label->mbr->raw_data)); 138 139 rc = block_write_direct(dev_handle, 0, 1, &label->mbr->raw_data); 143 140 block_fini(dev_handle); 144 if (rc != EOK) { 145 return rc; 146 } 147 148 return EOK; 149 } 150 151 /** Decide whether this is an actual MBR or a Protective MBR from GPT 152 * 153 * @param mbr the actual MBR to decide upon 154 * 155 * @return 1 if MBR, 0 if GPT 141 142 return rc; 143 } 144 145 /** Decide whether this is an actual MBR or a Protective MBR for GPT 146 * 147 * @param label Label to decide upon. 148 * 149 * @return True if MBR. 150 * @return False if Protective MBR for GPT. 151 * 156 152 */ 157 153 int mbr_is_mbr(mbr_label_t *label) 158 154 { 159 return (label->mbr->raw_data.pte[0].ptype != PT_GPT) ? 1 : 0; 160 } 161 162 /** Parse partitions from MBR, freeing previous partitions if any 163 * NOTE: it is assumed mbr_read_mbr(label) was called before. 164 * @param label MBR to be parsed 165 * 166 * @return linked list of partitions or NULL on error 155 return (label->mbr->raw_data.pte[0].ptype != PT_GPT); 156 } 157 158 /** Parse partitions from MBR (freeing previous partitions if any) 159 * 160 * It is assumed that mbr_read_mbr() was called before. 161 * 162 * @param label Label to be parsed. 163 * 164 * @return EOK on success, error code on error. 165 * 167 166 */ 168 167 int mbr_read_partitions(mbr_label_t *label) 169 168 { 170 if ( label == NULL || label->mbr == NULL)169 if ((label == NULL) || (label->mbr == NULL)) 171 170 return EINVAL; 172 173 int rc, rc_ext;174 unsigned int i;175 mbr_part_t *p;176 mbr_part_t *ext = NULL;177 171 178 172 if (label->parts != NULL) … … 180 174 181 175 label->parts = mbr_alloc_partitions(); 182 if (label->parts == NULL) {176 if (label->parts == NULL) 183 177 return ENOMEM; 184 } 178 179 mbr_part_t *extended = NULL; 185 180 186 181 /* Generate the primary partitions */ 187 for ( i = 0; i < N_PRIMARY; ++i) {182 for (unsigned int i = 0; i < N_PRIMARY; i++) { 188 183 if (label->mbr->raw_data.pte[i].ptype == PT_UNUSED) 189 184 continue; 190 185 191 p = mbr_alloc_partition(); 192 if (p == NULL) { 193 printf(LIBMBR_NAME ": Error on memory allocation.\n"); 186 mbr_part_t *partition = mbr_alloc_partition(); 187 if (partition == NULL) { 194 188 mbr_free_partitions(label->parts); 195 189 return ENOMEM; 196 190 } 197 191 198 rc_ext = decode_part(&(label->mbr->raw_data.pte[i]), p, 0); 199 mbr_set_flag(p, ST_LOGIC, false); 200 rc = mbr_add_partition(label, p); 192 int is_extended = 193 decode_part(&label->mbr->raw_data.pte[i], partition, 0); 194 195 mbr_set_flag(partition, ST_LOGIC, false); 196 197 int rc = mbr_add_partition(label, partition); 201 198 if (rc != ERR_OK) { 202 printf(LIBMBR_NAME ": Error occured during decoding the MBR. (%d)\n" \203 LIBMBR_NAME ": MBR is invalid.\n", rc);204 199 mbr_free_partitions(label->parts); 205 200 return EINVAL; 206 201 } 207 202 208 if (rc_ext) { 209 ext = p; 210 label->parts->l_extended = &p->link; 211 } 212 } 213 214 /* Fill in the primary partitions and generate logical ones, if any */ 215 rc = decode_logical(label, ext); 216 if (rc != EOK) { 217 printf(LIBMBR_NAME ": Error during decoding logical partitions: %d - %s.\n" \ 218 LIBMBR_NAME ": Partition list may be incomplete.\n", rc, str_error(rc)); 219 return rc; 220 } 221 222 return EOK; 203 if (is_extended) { 204 extended = partition; 205 label->parts->l_extended = &partition->link; 206 } 207 } 208 209 /* Fill in the primary partitions and generate logical ones (if any) */ 210 return decode_logical(label, extended); 223 211 } 224 212 225 213 /** Write MBR and partitions to device 226 * @param label label to write 227 * @param dev_handle device to write the data to 228 * 229 * @return returns EOK on succes, specific error code otherwise 214 * 215 * @param label Label to write. 216 * @param dev_handle Device to write the data to. 217 * 218 * @return EOK on success, specific error code otherwise. 219 * 230 220 */ 231 221 int mbr_write_partitions(mbr_label_t *label, service_id_t dev_handle) … … 237 227 label->mbr = mbr_alloc_mbr(); 238 228 239 int i = 0; 240 int rc; 241 mbr_part_t *p; 242 mbr_part_t *ext = (label->parts->l_extended == NULL) ? NULL 243 : list_get_instance(label->parts->l_extended, mbr_part_t, link); 244 245 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 246 if (rc != EOK) { 247 printf(LIBMBR_NAME ": Error while initializing libblock: %d - %s.\n", rc, str_error(rc)); 229 int rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 230 if (rc != EOK) 248 231 return rc; 249 } 250 251 link_t *l = label->parts->list.head.next; 252 253 /* Encoding primary partitions */ 254 for (i = 0; i < N_PRIMARY; i++) { 255 p = list_get_instance(l, mbr_part_t, link); 256 encode_part(p, &(label->mbr->raw_data.pte[i]), 0, false); 257 l = l->next; 258 } 259 260 label->mbr->raw_data.signature = host2uint16_t_le(BR_SIGNATURE); 261 262 /* Writing MBR */ 263 rc = block_write_direct(dev_handle, 0, 1, &(label->mbr->raw_data)); 264 if (rc != EOK) { 265 printf(LIBMBR_NAME ": Error while writing MBR : %d - %s.\n", rc, str_error(rc)); 232 233 mbr_part_t *partition = NULL; 234 mbr_part_t *extended = NULL; 235 236 if (label->parts->l_extended != NULL) 237 extended = list_get_instance(label->parts->l_extended, 238 mbr_part_t, link); 239 240 link_t *link = label->parts->list.head.next; 241 242 /* Encode primary partitions */ 243 for (unsigned int i = 0; i < N_PRIMARY; i++) { 244 partition = list_get_instance(link, mbr_part_t, link); 245 246 encode_part(partition, &label->mbr->raw_data.pte[i], 0, false); 247 link = link->next; 248 } 249 250 /* Write MBR */ 251 rc = block_write_direct(dev_handle, 0, 1, &label->mbr->raw_data); 252 if ((rc != EOK) || (extended == NULL)) 266 253 goto end; 267 } 268 269 if (ext == NULL) { 270 rc = EOK; 254 255 uint32_t base = extended->start_addr; 256 mbr_part_t *prev_partition; 257 258 /* Encode and write first logical partition */ 259 if (link != &label->parts->list.head) { 260 partition = list_get_instance(link, mbr_part_t, link); 261 262 partition->ebr_addr = base; 263 encode_part(partition, &partition->ebr->pte[0], base, false); 264 link = link->next; 265 } else { 266 /* 267 * If there was an extended partition but no logical partitions, 268 * we should overwrite the space where the first logical 269 * partitions's EBR would have been. There might be some 270 * garbage from the past. 271 */ 272 273 br_block_t *br = alloc_br(); 274 rc = block_write_direct(dev_handle, base, 1, br); 275 if (rc != EOK) 276 goto end; 277 278 free(br); 271 279 goto end; 272 280 } 273 281 274 uint32_t base = ext->start_addr; 275 mbr_part_t *prev_p; 276 277 /* Note for future changes: Some thought has been put into design 278 * and implementation. If you don't have to change it, don't. Other 279 * designs have been tried, this came out as the least horror with 280 * as much power over it as you can get. */ 281 282 /* Encoding and writing first logical partition */ 283 if (l != &(label->parts->list.head)) { 284 p = list_get_instance(l, mbr_part_t, link); 285 p->ebr_addr = base; 286 encode_part(p, &(p->ebr->pte[0]), base, false); 287 l = l->next; 288 } else { 289 /* If there was an extended but no logical, we should overwrite 290 * the space where the first logical's EBR would have been. There 291 * might be some garbage from the past. */ 292 br_block_t * tmp = alloc_br(); 293 rc = block_write_direct(dev_handle, base, 1, tmp); 294 if (rc != EOK) { 295 printf(LIBMBR_NAME ": Error while writing EBR: %d - %s.\n", rc, str_error(rc)); 296 goto end; 297 } 298 free(tmp); 299 rc = EOK; 300 goto end; 301 } 302 303 prev_p = p; 304 305 /* Check EBR addresses 306 * This piece of code saves previous EBR placements from other 307 * software. But if our user modifies the logical partition chain, 308 * we have to fix those placements if needed.*/ 309 link_t *l_ebr = l; 310 link_t *l_iter; 311 mbr_part_t *tmp = mbr_alloc_partition(); 312 tmp->length = 1; 313 while (l_ebr != &(label->parts->list.head)) { 314 p = list_get_instance(l_ebr, mbr_part_t, link); 315 tmp->start_addr = p->ebr_addr; 316 317 l_iter = l; 318 while (l_iter != &(label->parts->list.head)) { 319 /* Checking whether EBR address makes sense. If not, we take a guess. 320 * So far this is simple, we just take the first preceeding sector. 321 * Fdisk always reserves at least 2048 sectors (1MiB), so it can have 322 * the EBR aligned as well as the partition itself. Parted reserves 323 * minimum one sector, like we do. 324 * 325 * Note that we know there is at least one sector free from previous checks. 326 * Also note that the user can set ebr_addr to their liking (if it's valid). */ 327 if (p->ebr_addr < base || p->ebr_addr >= base + ext->length || 328 check_overlap(tmp, list_get_instance(l_iter, mbr_part_t, link))) { 329 p->ebr_addr = p->start_addr - 1; 282 prev_partition = partition; 283 284 /* 285 * Check EBR addresses: The code saves previous EBR 286 * placements from other software. But if our user 287 * modifies the logical partition chain, we have to 288 * fix those placements if needed. 289 */ 290 291 link_t *link_ebr = link; 292 link_t *link_iter; 293 294 mbr_part_t tmp_partition; 295 tmp_partition.length = 1; 296 297 while (link_ebr != &label->parts->list.head) { 298 partition = list_get_instance(link_ebr, mbr_part_t, link); 299 300 tmp_partition.start_addr = partition->ebr_addr; 301 302 link_iter = link; 303 while (link_iter != &label->parts->list.head) { 304 /* 305 * Check whether EBR address makes sense. If not, we take 306 * a guess. So far this is simple, we just take the first 307 * preceeding sector. FDisk always reserves at least 2048 308 * sectors (1 MiB), so it can have the EBR aligned as well 309 * as the partition itself. Parted reserves minimum one 310 * sector, like we do. 311 * 312 * Note that we know there is at least one sector free from 313 * previous checks. Also note that the user can set ebr_addr 314 * to their liking (if it is valid). 315 */ 316 317 if ((partition->ebr_addr < base) || 318 (partition->ebr_addr >= base + extended->length) || 319 (check_overlap(&tmp_partition, 320 list_get_instance(link_iter, mbr_part_t, link)))) { 321 partition->ebr_addr = partition->start_addr - 1; 330 322 break; 331 323 } 332 324 333 l _iter = l_iter->next;334 } 335 336 l _ebr = l_ebr->next;337 } 338 mbr_free_partition(tmp);339 340 /* Encoding and writing logical partitions */341 while (l != &(label->parts->list.head)) {342 p = list_get_instance(l, mbr_part_t, link);343 344 345 encode_part(p , &(p->ebr->pte[0]), p->ebr_addr, false);346 encode_part(p, &(prev_p->ebr->pte[1]),base, true);347 348 rc = block_write_direct(dev_handle, prev_p ->ebr_addr, 1, prev_p->ebr);349 if (rc != EOK) {350 printf(LIBMBR_NAME ": Error while writing EBR: %d - %s.\n", rc, str_error(rc));325 link_iter = link_iter->next; 326 } 327 328 link_ebr = link_ebr->next; 329 } 330 331 /* Encode and write logical partitions */ 332 while (link != &label->parts->list.head) { 333 partition = list_get_instance(link, mbr_part_t, link); 334 335 encode_part(partition, &partition->ebr->pte[0], 336 partition->ebr_addr, false); 337 encode_part(partition, &prev_partition->ebr->pte[1], 338 base, true); 339 340 rc = block_write_direct(dev_handle, prev_partition->ebr_addr, 1, 341 prev_partition->ebr); 342 if (rc != EOK) 351 343 goto end; 352 } 353 354 prev_p = p; 355 l = l->next; 356 } 357 358 /* write the last EBR */ 359 encode_part(NULL, &(prev_p->ebr->pte[1]), 0, false); 360 rc = block_write_direct(dev_handle, prev_p->ebr_addr, 1, prev_p->ebr); 361 if (rc != EOK) { 362 printf(LIBMBR_NAME ": Error while writing EBR: %d - %s.\n", rc, str_error(rc)); 363 goto end; 364 } 365 366 rc = EOK; 344 345 prev_partition = partition; 346 link = link->next; 347 } 348 349 /* Write the last EBR */ 350 encode_part(NULL, &prev_partition->ebr->pte[1], 0, false); 351 rc = block_write_direct(dev_handle, prev_partition->ebr_addr, 352 1, prev_partition->ebr); 367 353 368 354 end: 369 355 block_fini(dev_handle); 370 371 356 return rc; 372 357 } 373 358 374 /** mbr_part_tconstructor */375 mbr_part_t * 376 { 377 mbr_part_t *p = malloc(sizeof(mbr_part_t));378 if (p == NULL) {359 /** Partition constructor */ 360 mbr_part_t *mbr_alloc_partition(void) 361 { 362 mbr_part_t *partition = malloc(sizeof(mbr_part_t)); 363 if (partition == NULL) 379 364 return NULL; 380 } 381 382 link_initialize(&(p->link)); 383 p->ebr = NULL; 384 p->type = PT_UNUSED; 385 p->status = 0; 386 p->start_addr = 0; 387 p->length = 0; 388 p->ebr_addr = 0; 389 390 return p; 391 } 392 393 /** mbr_partitions_t constructor */ 394 mbr_partitions_t * mbr_alloc_partitions(void) 365 366 link_initialize(&partition->link); 367 partition->ebr = NULL; 368 partition->type = PT_UNUSED; 369 partition->status = 0; 370 partition->start_addr = 0; 371 partition->length = 0; 372 partition->ebr_addr = 0; 373 374 return partition; 375 } 376 377 /** Partitions constructor */ 378 mbr_partitions_t *mbr_alloc_partitions(void) 395 379 { 396 380 mbr_partitions_t *parts = malloc(sizeof(mbr_partitions_t)); 397 if (parts == NULL) {381 if (parts == NULL) 398 382 return NULL; 399 } 400 401 list_initialize(&(parts->list)); 383 384 list_initialize(&parts->list); 402 385 parts->n_primary = 0; 403 386 parts->n_logical = 0; 404 387 parts->l_extended = NULL; 405 388 406 /* add blank primary partitions */ 407 int i; 408 mbr_part_t *p; 409 for (i = 0; i < N_PRIMARY; ++i) { 410 p = mbr_alloc_partition(); 411 if (p == NULL) { 389 /* Add blank primary partitions */ 390 for (unsigned int i = 0; i < N_PRIMARY; ++i) { 391 mbr_part_t *part = mbr_alloc_partition(); 392 if (part == NULL) { 412 393 mbr_free_partitions(parts); 413 394 return NULL; 414 395 } 415 list_append(&(p->link), &(parts->list));416 }417 418 396 397 list_append(&part->link, &parts->list); 398 } 399 419 400 return parts; 420 401 } 421 402 422 403 /** Add partition 423 * Performs checks, sorts the list. 424 * 425 * @param label label to add to 426 * @param p partition to add 427 * 428 * @return ERR_OK (0) on success, other MBR_ERR_VAL otherwise 429 */ 430 mbr_err_val mbr_add_partition(mbr_label_t *label, mbr_part_t *p) 431 { 432 int rc1, rc2; 404 * 405 * Perform checks, sort the list. 406 * 407 * @param label Label to add to. 408 * @param part Partition to add. 409 * 410 * @return ERR_OK on success, other MBR_ERR_VAL otherwise 411 * 412 */ 413 mbr_err_val mbr_add_partition(mbr_label_t *label, mbr_part_t *part) 414 { 415 int rc = block_init(EXCHANGE_ATOMIC, label->device, 512); 416 if ((rc != EOK) && (rc != EEXIST)) 417 return ERR_LIBBLOCK; 418 433 419 aoff64_t nblocks; 434 435 rc1 = block_init(EXCHANGE_ATOMIC, label->device, 512); 436 if (rc1 != EOK && rc1 != EEXIST) { 437 printf(LIBMBR_NAME ": Error during libblock init: %d - %s.\n", rc1, str_error(rc1)); 420 int ret = block_get_nblocks(label->device, &nblocks); 421 422 if (rc != EEXIST) 423 block_fini(label->device); 424 425 if (ret != EOK) 438 426 return ERR_LIBBLOCK; 439 } 440 441 rc2 = block_get_nblocks(label->device, &nblocks); 442 443 if (rc1 != EEXIST) 444 block_fini(label->device); 445 446 if (rc2 != EOK) { 447 printf(LIBMBR_NAME ": Error while getting number of blocks: %d - %s.\n", rc2, str_error(rc2)); 448 return ERR_LIBBLOCK; 449 } 450 451 if ((aoff64_t) p->start_addr + p->length > nblocks) 427 428 if ((aoff64_t) part->start_addr + part->length > nblocks) 452 429 return ERR_OUT_BOUNDS; 453 430 … … 455 432 label->parts = mbr_alloc_partitions(); 456 433 if (label->parts == NULL) 457 return ENOMEM; //FIXME! merge mbr_err_val into errno.h458 }459 460 if (mbr_get_flag(p, ST_LOGIC))461 /* adding logical partition */462 return mbr_add_logical(label, p );434 // FIXME! merge mbr_err_val into errno.h 435 return ENOMEM; 436 } 437 438 if (mbr_get_flag(part, ST_LOGIC)) 439 return mbr_add_logical(label, part); 463 440 else 464 /* adding primary */ 465 return mbr_add_primary(label, p); 441 return mbr_add_primary(label, part); 466 442 } 467 443 468 444 /** Remove partition 469 * Removes partition by index, indexed from zero. When removing extended 470 * partition, all logical partitions get removed as well. 471 * 472 * @param label label to remove from 473 * @param idx index of the partition to remove 474 * 475 * @return EOK on success, EINVAL if idx invalid 445 * 446 * Remove partition (indexed from zero). When removing the extended 447 * partition, all logical partitions get removed as well. 448 * 449 * @param label Label to remove from. 450 * @param idx Index of the partition to remove. 451 * 452 * @return EOK on success. 453 * @return EINVAL if the index is invalid. 454 * 476 455 */ 477 456 int mbr_remove_partition(mbr_label_t *label, size_t idx) 478 457 { 479 link_t *l = list_nth(&(label->parts->list), idx);480 if (l == NULL)458 link_t *link = list_nth(&label->parts->list, idx); 459 if (link == NULL) 481 460 return EINVAL; 482 461 483 mbr_part_t *p; 484 485 /* If we're removing an extended partition, remove all logical as well */ 486 if (l == label->parts->l_extended) { 462 /* 463 * If removing the extended partition, remove all 464 * logical partitions as well. 465 */ 466 if (link == label->parts->l_extended) { 487 467 label->parts->l_extended = NULL; 488 468 489 link_t *it = l->next; 490 link_t *next_it; 491 while (it != &(label->parts->list.head)) { 492 next_it = it->next; 469 link_t *iterator = link->next; 470 link_t *next; 471 472 while (iterator != &label->parts->list.head) { 473 next = iterator->next; 474 mbr_part_t *partition = 475 list_get_instance(iterator, mbr_part_t, link); 493 476 494 p = list_get_instance(it, mbr_part_t, link); 495 if (mbr_get_flag(p, ST_LOGIC)) { 496 list_remove(it); 497 label->parts->n_logical -= 1; 498 mbr_free_partition(p); 477 if (mbr_get_flag(partition, ST_LOGIC)) { 478 list_remove(iterator); 479 label->parts->n_logical--; 480 mbr_free_partition(partition); 499 481 } 500 482 501 it = next_it; 502 } 503 483 iterator = next; 484 } 504 485 } 505 486 506 487 /* Remove the partition itself */ 507 p = list_get_instance(l, mbr_part_t, link); 508 if (mbr_get_flag(p, ST_LOGIC)) { 509 label->parts->n_logical -= 1; 510 list_remove(l); 511 mbr_free_partition(p); 488 mbr_part_t *partition = 489 list_get_instance(link, mbr_part_t, link); 490 491 if (mbr_get_flag(partition, ST_LOGIC)) { 492 label->parts->n_logical--; 493 list_remove(link); 494 mbr_free_partition(partition); 512 495 } else { 513 /* Cannot remove primary - it would break ordering, just zero it */ 514 label->parts->n_primary -= 1; 515 p->type = 0; 516 p->status = 0; 517 p->start_addr = 0; 518 p->length = 0; 519 p->ebr_addr = 0; 496 /* 497 * Cannot remove a primary partition without 498 * breaking the ordering. Just zero it. 499 */ 500 label->parts->n_primary--; 501 partition->type = 0; 502 partition->status = 0; 503 partition->start_addr = 0; 504 partition->length = 0; 505 partition->ebr_addr = 0; 520 506 } 521 507 … … 523 509 } 524 510 525 /** mbr_part_t destructor */ 526 void mbr_free_partition(mbr_part_t *p) 527 { 528 if (p->ebr != NULL) 529 free(p->ebr); 530 free(p); 531 } 532 533 /** Get flag bool value */ 534 int mbr_get_flag(mbr_part_t *p, MBR_FLAGS flag) 535 { 536 return (p->status & (1 << flag)) ? 1 : 0; 537 } 538 539 /** Set a specifig status flag to a value */ 540 void mbr_set_flag(mbr_part_t *p, MBR_FLAGS flag, bool value) 541 { 542 uint16_t status = p->status; 543 544 if (value) 545 status = status | (1 << flag); 511 /** Partition destructor */ 512 void mbr_free_partition(mbr_part_t *partition) 513 { 514 if (partition->ebr != NULL) 515 free(partition->ebr); 516 517 free(partition); 518 } 519 520 /** Check for flag */ 521 int mbr_get_flag(mbr_part_t *partition, mbr_flags_t flag) 522 { 523 return (partition->status & (1 << flag)); 524 } 525 526 /** Set a specific status flag */ 527 void mbr_set_flag(mbr_part_t *partition, mbr_flags_t flag, bool set) 528 { 529 if (set) 530 partition->status |= 1 << flag; 546 531 else 547 status = status ^ (status & (1 << flag)); 548 549 p->status = status; 532 partition->status &= ~((uint16_t) (1 << flag)); 550 533 } 551 534 … … 553 536 uint32_t mbr_get_next_aligned(uint32_t addr, unsigned int alignment) 554 537 { 555 uint32_t div = addr / alignment; 556 return (div + 1) * alignment; 557 } 558 559 list_t * mbr_get_list(mbr_label_t *label) 538 return ALIGN_UP(addr + 1, alignment); 539 } 540 541 list_t *mbr_get_list(mbr_label_t *label) 560 542 { 561 543 if (label->parts != NULL) 562 return & (label->parts->list);544 return &label->parts->list; 563 545 else 564 546 return NULL; 565 547 } 566 548 567 mbr_part_t * 549 mbr_part_t *mbr_get_first_partition(mbr_label_t *label) 568 550 { 569 551 list_t *list = mbr_get_list(label); 570 if ( list != NULL && !list_empty(list))552 if ((list != NULL) && (!list_empty(list))) 571 553 return list_get_instance(list->head.next, mbr_part_t, link); 572 554 else … … 574 556 } 575 557 576 mbr_part_t * mbr_get_next_partition(mbr_label_t *label, mbr_part_t *p)558 mbr_part_t *mbr_get_next_partition(mbr_label_t *label, mbr_part_t *partition) 577 559 { 578 560 list_t *list = mbr_get_list(label); 579 if ( list != NULL && &(p->link) != list_last(list))580 return list_get_instance(p ->link.next, mbr_part_t, link);561 if ((list != NULL) && (&partition->link != list_last(list))) 562 return list_get_instance(partition->link.next, mbr_part_t, link); 581 563 else 582 564 return NULL; 583 565 } 584 566 585 /** Just a wrapper for free() */586 567 void mbr_free_mbr(mbr_t *mbr) 587 568 { … … 591 572 /** Free partition list 592 573 * 593 * @param parts partition list to be freed 574 * @param parts Partition list to be freed 575 * 594 576 */ 595 577 void mbr_free_partitions(mbr_partitions_t *parts) 596 578 { 597 579 list_foreach_safe(parts->list, cur_link, next) { 598 mbr_part_t *p = list_get_instance(cur_link, mbr_part_t, link);580 mbr_part_t *partition = list_get_instance(cur_link, mbr_part_t, link); 599 581 list_remove(cur_link); 600 mbr_free_partition(p );601 } 602 582 mbr_free_partition(partition); 583 } 584 603 585 free(parts); 604 586 } 605 587 606 /* Internal functions follow */ 607 608 static br_block_t *alloc_br() 588 static br_block_t *alloc_br(void) 609 589 { 610 590 br_block_t *br = malloc(sizeof(br_block_t)); … … 618 598 } 619 599 620 /** Parse partition entry to mbr_part_t 621 * @return returns 1, if extended partition, 0 otherwise 622 * */ 623 static int decode_part(pt_entry_t *src, mbr_part_t *trgt, uint32_t base) 624 { 625 trgt->type = src->ptype; 626 627 trgt->status = (trgt->status & 0xFF00) | (uint16_t) src->status; 628 629 trgt->start_addr = uint32_t_le2host(src->first_lba) + base; 630 trgt->length = uint32_t_le2host(src->length); 631 632 return (src->ptype == PT_EXTENDED) ? 1 : 0; 633 } 634 635 /** Parse MBR contents to mbr_part_t list */ 636 static int decode_logical(mbr_label_t *label, mbr_part_t * ext) 637 { 638 int rc; 639 mbr_part_t *p; 640 641 if (ext == NULL) 600 /** Decode partition entry */ 601 static int decode_part(pt_entry_t *src, mbr_part_t *partition, uint32_t base) 602 { 603 partition->type = src->ptype; 604 partition->status = (partition->status & 0xff00) | (uint16_t) src->status; 605 partition->start_addr = uint32_t_le2host(src->first_lba) + base; 606 partition->length = uint32_t_le2host(src->length); 607 608 return (src->ptype == PT_EXTENDED); 609 } 610 611 /** Parse logical partitions */ 612 static int decode_logical(mbr_label_t *label, mbr_part_t *extended) 613 { 614 if (extended == NULL) 642 615 return EOK; 643 644 uint32_t base = ext->start_addr; 616 617 br_block_t *ebr = alloc_br(); 618 if (ebr == NULL) 619 return ENOMEM; 620 621 uint32_t base = extended->start_addr; 645 622 uint32_t addr = base; 646 br_block_t *ebr; 647 648 rc = block_init(EXCHANGE_ATOMIC, label->device, 512); 623 624 int rc = block_init(EXCHANGE_ATOMIC, label->device, 512); 649 625 if (rc != EOK) 650 return rc; 651 652 ebr = alloc_br(); 653 if (ebr == NULL) { 626 goto end; 627 628 rc = block_read_direct(label->device, addr, 1, ebr); 629 if (rc != EOK) 630 goto end; 631 632 if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) { 633 rc = EINVAL; 634 goto end; 635 } 636 637 if (ebr->pte[0].ptype == PT_UNUSED) { 638 rc = EOK; 639 goto end; 640 } 641 642 mbr_part_t *partition = mbr_alloc_partition(); 643 if (partition == NULL) { 654 644 rc = ENOMEM; 655 645 goto end; 656 646 } 657 647 658 rc = block_read_direct(label->device, addr, 1, ebr); 659 if (rc != EOK) { 660 goto free_ebr_end; 661 } 662 663 if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) { 664 rc = EINVAL; 665 goto free_ebr_end; 666 } 667 668 if (ebr->pte[0].ptype == PT_UNUSED) { 669 rc = EOK; 670 goto free_ebr_end; 671 } 672 673 p = mbr_alloc_partition(); 674 if (p == NULL) { 675 rc = ENOMEM; 676 goto free_ebr_end; 677 } 678 679 decode_part(&(ebr->pte[0]), p, base); 680 mbr_set_flag(p, ST_LOGIC, true); 681 p->ebr = ebr; 682 p->ebr_addr = addr; 683 rc = mbr_add_partition(label, p); 684 if (rc != ERR_OK) 685 return EINVAL; 648 decode_part(&ebr->pte[0], partition, base); 649 mbr_set_flag(partition, ST_LOGIC, true); 650 partition->ebr = ebr; 651 partition->ebr_addr = addr; 652 653 rc = mbr_add_partition(label, partition); 654 if (rc != ERR_OK) 655 goto end; 686 656 687 657 addr = uint32_t_le2host(ebr->pte[1].first_lba) + base; 688 658 689 659 while (ebr->pte[1].ptype != PT_UNUSED) { 690 691 ebr = alloc_br(); 692 if (ebr == NULL) { 660 rc = block_read_direct(label->device, addr, 1, ebr); 661 if (rc != EOK) 662 goto end; 663 664 if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) { 665 rc = EINVAL; 666 goto end; 667 } 668 669 mbr_part_t *partition = mbr_alloc_partition(); 670 if (partition == NULL) { 693 671 rc = ENOMEM; 694 672 goto end; 695 673 } 696 674 697 rc = block_read_direct(label->device, addr, 1, ebr); 698 if (rc != EOK) { 699 goto free_ebr_end; 700 } 701 702 if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) { 703 rc = EINVAL; 704 goto free_ebr_end; 705 } 706 707 p = mbr_alloc_partition(); 708 if (p == NULL) { 709 rc = ENOMEM; 710 goto free_ebr_end; 711 } 712 713 decode_part(&(ebr->pte[0]), p, addr); 714 mbr_set_flag(p, ST_LOGIC, true); 715 p->ebr = ebr; 716 p->ebr_addr = addr; 717 rc = mbr_add_partition(label, p); 675 decode_part(&ebr->pte[0], partition, addr); 676 mbr_set_flag(partition, ST_LOGIC, true); 677 partition->ebr = ebr; 678 partition->ebr_addr = addr; 679 680 rc = mbr_add_partition(label, partition); 718 681 if (rc != ERR_OK) 719 return EINVAL;682 goto end; 720 683 721 684 addr = uint32_t_le2host(ebr->pte[1].first_lba) + base; … … 723 686 724 687 rc = EOK; 725 goto end;726 727 free_ebr_end:728 free(ebr);729 688 730 689 end: 690 // FIXME possible memory leaks 731 691 block_fini(label->device); 732 692 … … 734 694 } 735 695 736 /** Convert mbr_part_t to pt_entry_t */ 737 static void encode_part(mbr_part_t * src, pt_entry_t * trgt, uint32_t base, bool ebr) 696 /** Encode partition entry */ 697 static void encode_part(mbr_part_t *src, pt_entry_t *entry, uint32_t base, 698 bool ebr) 738 699 { 739 700 if (src != NULL) { 740 trgt->status = (uint8_t) (src->status & 0xFF); 741 /* ingoring CHS */ 742 trgt->first_chs[0] = 0xFE; 743 trgt->first_chs[1] = 0xFF; 744 trgt->first_chs[2] = 0xFF; 745 trgt->last_chs[0] = 0xFE; 746 trgt->last_chs[1] = 0xFF; 747 trgt->last_chs[2] = 0xFF; 748 if (ebr) { /* encoding reference to EBR */ 749 trgt->ptype = PT_EXTENDED_LBA; 750 trgt->first_lba = host2uint32_t_le(src->ebr_addr - base); 751 trgt->length = host2uint32_t_le(src->length + src->start_addr - src->ebr_addr); 752 } else { /* encoding reference to partition */ 753 trgt->ptype = src->type; 754 trgt->first_lba = host2uint32_t_le(src->start_addr - base); 755 trgt->length = host2uint32_t_le(src->length); 756 } 757 758 if (trgt->ptype == PT_UNUSED) 759 memset(trgt, 0, sizeof(pt_entry_t)); 760 } else { 761 memset(trgt, 0, sizeof(pt_entry_t)); 762 } 763 } 764 765 /** Check whether two partitions overlap 766 * 767 * @return true/false 768 */ 769 static bool check_overlap(mbr_part_t * p1, mbr_part_t * p2) 770 { 771 if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length <= p2->start_addr) { 701 entry->status = (uint8_t) src->status & 0xff; 702 703 /* Ignore CHS */ 704 entry->first_chs[0] = 0xfe; 705 entry->first_chs[1] = 0xff; 706 entry->first_chs[2] = 0xff; 707 entry->last_chs[0] = 0xfe; 708 entry->last_chs[1] = 0xff; 709 entry->last_chs[2] = 0xff; 710 711 if (ebr) { 712 /* Encode reference to EBR */ 713 entry->ptype = PT_EXTENDED_LBA; 714 entry->first_lba = host2uint32_t_le(src->ebr_addr - base); 715 entry->length = host2uint32_t_le(src->length + src->start_addr - 716 src->ebr_addr); 717 } else { 718 /* Encode reference to partition */ 719 entry->ptype = src->type; 720 entry->first_lba = host2uint32_t_le(src->start_addr - base); 721 entry->length = host2uint32_t_le(src->length); 722 } 723 724 if (entry->ptype == PT_UNUSED) 725 memset(entry, 0, sizeof(pt_entry_t)); 726 } else 727 memset(entry, 0, sizeof(pt_entry_t)); 728 } 729 730 /** Check whether two partitions overlap */ 731 static bool check_overlap(mbr_part_t *part1, mbr_part_t *part2) 732 { 733 if ((part1->start_addr < part2->start_addr) && 734 (part1->start_addr + part1->length <= part2->start_addr)) 772 735 return false; 773 } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length <= p1->start_addr) { 736 737 if ((part1->start_addr > part2->start_addr) && 738 (part2->start_addr + part2->length <= part1->start_addr)) 774 739 return false; 775 } 776 740 777 741 return true; 778 742 } 779 743 780 /** Check whether one partition encapsulates the other 781 * 782 * @return true/false 783 */ 784 static bool check_encaps(mbr_part_t * inner, mbr_part_t * outer) 785 { 786 if (inner->start_addr <= outer->start_addr || outer->start_addr + outer->length <= inner->start_addr) { 744 /** Check whether one partition encapsulates the other */ 745 static bool check_encaps(mbr_part_t *inner, mbr_part_t *outer) 746 { 747 if ((inner->start_addr <= outer->start_addr) || 748 (outer->start_addr + outer->length <= inner->start_addr)) 787 749 return false; 788 } else if (outer->start_addr + outer->length < inner->start_addr + inner->length) { 750 751 if (outer->start_addr + outer->length < inner->start_addr + inner->length) 789 752 return false; 790 } 791 753 792 754 return true; 793 755 } 794 756 795 /** Check whether one partition preceeds the other 796 * 797 * @return true/false 798 */ 799 static bool check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee) 757 /** Check whether one partition preceeds the other */ 758 static bool check_preceeds(mbr_part_t *preceeder, mbr_part_t *precedee) 800 759 { 801 760 return preceeder->start_addr < precedee->start_addr; 802 761 } 803 762 804 mbr_err_val mbr_add_primary(mbr_label_t *label, mbr_part_t *p )805 { 806 if (label->parts->n_primary == 4) {763 mbr_err_val mbr_add_primary(mbr_label_t *label, mbr_part_t *part) 764 { 765 if (label->parts->n_primary == 4) 807 766 return ERR_PRIMARY_FULL; 808 } 809 810 /* Check if partition makes space for MBR itself. */ 811 if (p->start_addr == 0) { 767 768 /* Check if partition makes space for MBR itself */ 769 if (part->start_addr == 0) 812 770 return ERR_OUT_BOUNDS; 813 }814 815 /* if it's extended, is there any other one? */816 if ((p->type == PT_EXTENDED || p->type == PT_EXTENDED_LBA) && label->parts->l_extended != NULL) {771 772 /* If it is an extended partition, is there any other one? */ 773 if (((part->type == PT_EXTENDED) || (part->type == PT_EXTENDED_LBA)) && 774 (label->parts->l_extended != NULL)) 817 775 return ERR_EXTENDED_PRESENT; 818 } 819 820 /* find a place and add it */ 776 777 /* Find a place and add it */ 821 778 mbr_part_t *iter; 822 779 mbr_part_t *empty = NULL; … … 825 782 if (empty == NULL) 826 783 empty = iter; 827 } else if (check_overlap(p , iter))784 } else if (check_overlap(part, iter)) 828 785 return ERR_OVERLAP; 829 786 } 830 787 831 list_insert_after(& (p->link), &(empty->link));832 list_remove(& (empty->link));788 list_insert_after(&part->link, &empty->link); 789 list_remove(&empty->link); 833 790 free(empty); 834 791 835 label->parts->n_primary += 1;836 837 if ( p->type == PT_EXTENDED || p->type == PT_EXTENDED_LBA)838 label->parts->l_extended = & (p->link);792 label->parts->n_primary++; 793 794 if ((part->type == PT_EXTENDED) || (part->type == PT_EXTENDED_LBA)) 795 label->parts->l_extended = &part->link; 839 796 840 797 return EOK; 841 798 } 842 799 843 mbr_err_val mbr_add_logical(mbr_label_t *label, mbr_part_t *p )844 { 845 /* is there any extended partition? */800 mbr_err_val mbr_add_logical(mbr_label_t *label, mbr_part_t *part) 801 { 802 /* Is there any extended partition? */ 846 803 if (label->parts->l_extended == NULL) 847 804 return ERR_NO_EXTENDED; 848 805 849 /* is the logical partition inside the extended one? */850 mbr_part_t *ext = list_get_instance(label->parts->l_extended, mbr_part_t, link);851 if (!check_encaps(p , ext))806 /* Is the logical partition inside the extended partition? */ 807 mbr_part_t *extended = list_get_instance(label->parts->l_extended, mbr_part_t, link); 808 if (!check_encaps(part, extended)) 852 809 return ERR_OUT_BOUNDS; 853 810 854 /* find a place for the new partition in a sorted linked list */811 /* Find a place for the new partition in a sorted linked list */ 855 812 bool first_logical = true; 856 813 mbr_part_t *iter; 857 814 mbr_part_foreach (label, iter) { 858 815 if (mbr_get_flag(iter, ST_LOGIC)) { 859 if (check_overlap(p , iter))816 if (check_overlap(part, iter)) 860 817 return ERR_OVERLAP; 861 if (check_preceeds(iter, p)) { 862 /* checking if there's at least one sector of space preceeding */ 863 if ((iter->start_addr + iter->length) >= p->start_addr - 1) 818 819 if (check_preceeds(iter, part)) { 820 /* Check if there is at least one sector of space preceeding */ 821 if ((iter->start_addr + iter->length) >= part->start_addr - 1) 864 822 return ERR_NO_EBR; 865 } else if (first_logical){ 866 /* First logical partition's EBR is before every other 867 * logical partition. Thus we don't check if this partition 868 * leaves enough space for it. */ 823 } else if (first_logical) { 824 /* 825 * First logical partition's EBR is before every other 826 * logical partition. Thus we do not check if this partition 827 * leaves enough space for it. 828 */ 869 829 first_logical = false; 870 830 } else { 871 /* checking if there's at least one sector of space following (for following partitions's EBR) */ 872 if ((p->start_addr + p->length) >= iter->start_addr - 1) 831 /* 832 * Check if there is at least one sector of space following 833 * (for following partitions's EBR). 834 */ 835 if ((part->start_addr + part->length) >= iter->start_addr - 1) 873 836 return ERR_NO_EBR; 874 837 } … … 876 839 } 877 840 878 /* alloc EBR if it's not already there */879 if (p ->ebr == NULL) {880 p ->ebr = alloc_br();881 if (p ->ebr == NULL) {841 /* Allocate EBR if it is not already there */ 842 if (part->ebr == NULL) { 843 part->ebr = alloc_br(); 844 if (part->ebr == NULL) 882 845 return ERR_NOMEM; 883 } 884 } 885 886 /* add it */ 887 list_append(&(p->link), &(label->parts->list)); 888 label->parts->n_logical += 1; 846 } 847 848 list_append(&part->link, &label->parts->list); 849 label->parts->n_logical++; 889 850 890 851 return EOK; 891 852 } 892 893 894 -
uspace/lib/mbr/libmbr.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 * … … 28 28 */ 29 29 30 30 /** @addtogroup libmbr 31 31 * @{ 32 32 */ … … 40 40 #include "mbr.h" 41 41 42 #define LIBMBR_NAME "libmbr" 42 /* 43 * WARNING: When changing both header and partitions, write first header, 44 * then partitions. The MBR headers' raw_data is not updated to follow 45 * partition changes. 46 * 47 * NOTE: Writing partitions writes the complete header as well. 48 */ 43 49 44 50 typedef enum { … … 48 54 /** Logical partition, 0 = primary, 1 = logical*/ 49 55 ST_LOGIC = 8 50 } MBR_FLAGS;56 } mbr_flags_t; 51 57 52 58 typedef enum { … … 77 83 } mbr_t; 78 84 79 80 85 /** Partition */ 81 86 typedef struct mbr_part { … … 91 96 uint32_t length; 92 97 /** Points to Extended Boot Record of logical partition */ 93 br_block_t * 98 br_block_t *ebr; 94 99 /** EBR address */ 95 100 uint32_t ebr_addr; … … 101 106 unsigned char n_primary; 102 107 /** Index to the extended partition in the array */ 103 link_t * 108 link_t *l_extended; 104 109 /** Number of logical partitions */ 105 110 unsigned int n_logical; … … 111 116 typedef struct mbr_label { 112 117 /** MBR header */ 113 mbr_t * 118 mbr_t *mbr; 114 119 /** Partition list */ 115 120 mbr_partitions_t * parts; … … 118 123 } mbr_label_t; 119 124 120 /* Alloc complete label structure */ 121 extern mbr_label_t * mbr_alloc_label(void); 125 #define mbr_part_foreach(label, iterator) \ 126 for (iterator = list_get_instance((label)->parts->list.head.next, mbr_part_t, link); \ 127 iterator != list_get_instance(&((label)->parts->list.head), mbr_part_t, link); \ 128 iterator = list_get_instance(iterator->link.next, mbr_part_t, link)) 129 130 extern mbr_label_t *mbr_alloc_label(void); 131 122 132 extern void mbr_set_device(mbr_label_t *, service_id_t); 123 124 /* Read/Write MBR header. 125 * WARNING: when changing both header and partitions, write first header, 126 * then partitions. The MBR headers' raw_data is NOT updated to follow 127 * partition changes. */ 128 extern mbr_t * mbr_alloc_mbr(void); 133 extern mbr_t *mbr_alloc_mbr(void); 129 134 extern int mbr_read_mbr(mbr_label_t *, service_id_t); 130 135 extern int mbr_write_mbr(mbr_label_t *, service_id_t); 131 136 extern int mbr_is_mbr(mbr_label_t *); 132 137 133 /* Read/Write/Set MBR partitions. 134 * NOTE: Writing partitions writes the complete header as well. */ 135 extern int mbr_read_partitions(mbr_label_t *); 136 extern int mbr_write_partitions(mbr_label_t *, service_id_t); 137 extern mbr_part_t * mbr_alloc_partition(void); 138 extern mbr_partitions_t * mbr_alloc_partitions(void); 139 extern mbr_err_val mbr_add_partition(mbr_label_t *, mbr_part_t *); 140 extern int mbr_remove_partition(mbr_label_t *, size_t); 141 extern int mbr_get_flag(mbr_part_t *, MBR_FLAGS); 142 extern void mbr_set_flag(mbr_part_t *, MBR_FLAGS, bool); 143 extern uint32_t mbr_get_next_aligned(uint32_t, unsigned int); 144 extern list_t * mbr_get_list(mbr_label_t *); 145 extern mbr_part_t * mbr_get_first_partition(mbr_label_t *); 146 extern mbr_part_t * mbr_get_next_partition(mbr_label_t *, mbr_part_t *); 138 extern int mbr_read_partitions(mbr_label_t *); 139 extern int mbr_write_partitions(mbr_label_t *, service_id_t); 140 extern mbr_part_t *mbr_alloc_partition(void); 141 extern mbr_partitions_t *mbr_alloc_partitions(void); 142 extern mbr_err_val mbr_add_partition(mbr_label_t *, mbr_part_t *); 143 extern int mbr_remove_partition(mbr_label_t *, size_t); 144 extern int mbr_get_flag(mbr_part_t *, mbr_flags_t); 145 extern void mbr_set_flag(mbr_part_t *, mbr_flags_t, bool); 146 extern uint32_t mbr_get_next_aligned(uint32_t, unsigned int); 147 extern list_t *mbr_get_list(mbr_label_t *); 148 extern mbr_part_t *mbr_get_first_partition(mbr_label_t *); 149 extern mbr_part_t *mbr_get_next_partition(mbr_label_t *, mbr_part_t *); 147 150 148 #define mbr_part_foreach(label, iterator) \149 for (iterator = list_get_instance((label)->parts->list.head.next, mbr_part_t, link); \150 iterator != list_get_instance(&((label)->parts->list.head), mbr_part_t, link); \151 iterator = list_get_instance(iterator->link.next, mbr_part_t, link))152 153 154 /* free() wrapper functions. */155 151 extern void mbr_free_label(mbr_label_t *); 156 152 extern void mbr_free_mbr(mbr_t *); … … 159 155 160 156 #endif 161 -
uspace/lib/mbr/mbr.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 * … … 39 39 #include <sys/types.h> 40 40 41 /** Number of primary partition records */ 42 #define N_PRIMARY 4 43 44 /** Boot record signature */ 45 #define BR_SIGNATURE 0xAA55 41 enum { 42 /** Number of primary partition records */ 43 N_PRIMARY = 4, 44 45 /** Boot record signature */ 46 BR_SIGNATURE = 0xAA55 47 }; 46 48 47 49 enum { … … 55 57 enum { 56 58 /** Unused partition entry */ 57 PT_UNUSED 59 PT_UNUSED = 0x00, 58 60 /** Extended partition */ 59 PT_EXTENDED 61 PT_EXTENDED = 0x05, 60 62 /** Extended partition with LBA */ 61 PT_EXTENDED_LBA 63 PT_EXTENDED_LBA = 0x0F, 62 64 /** GPT Protective partition */ 63 PT_GPT 65 PT_GPT = 0xEE, 64 66 }; 65 67
Note:
See TracChangeset
for help on using the changeset viewer.