Changeset 7570e800 in mainline
- Timestamp:
- 2012-12-18T23:05:20Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5beb1ff
- Parents:
- cbd64057
- Location:
- uspace/lib
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/Makefile
rcbd64057 r7570e800 66 66 generic/cap.c \ 67 67 generic/cfg.c \ 68 generic/checksum.c \ 68 69 generic/clipboard.c \ 69 70 generic/devman.c \ -
uspace/lib/gpt/libgpt.c
rcbd64057 r7570e800 38 38 */ 39 39 40 #include <ipc/bd.h> 41 #include <async.h> 42 #include <stdio.h> 43 #include <block.h> 44 #include <errno.h> 45 #include <stdlib.h> 46 #include <assert.h> 47 #include <byteorder.h> 40 48 #include <checksum.h> 41 #include <errno.h>42 49 #include <mem.h> 43 50 44 51 #include "libgpt.h" 52 53 static int load_and_check_header(service_id_t handle, aoff64_t addr, size_t b_size, gpt_header_t * header); 54 static gpt_parts_t * alloc_part_array(uint32_t num); 55 static int extend_part_array(gpt_parts_t * p); 56 static int reduce_part_array(gpt_parts_t * p); 57 static long long nearest_larger_int(double a); 45 58 46 59 /** Read GPT from specific device … … 66 79 } 67 80 68 gpt-> header_lba = malloc(b_size);// We might need only sizeof(gpt_header_t),81 gpt->raw_data = malloc(b_size);// We might need only sizeof(gpt_header_t), 69 82 if (gpt == NULL) { // but we should follow specs and have 70 83 free(gpt); // zeroes through all the rest of the block … … 74 87 75 88 76 rc = load_and_check_header( handle, GPT_HDR_BA, gpt->header_lba);89 rc = load_and_check_header(dev_handle, GPT_HDR_BA, b_size, gpt->raw_data); 77 90 if (rc == EBADCHECKSUM || rc == EINVAL) { 78 91 aoff64_t n_blocks; … … 83 96 } 84 97 85 rc = load_and_check_header( handle, n_blocks - 1, gpt->header_lba);98 rc = load_and_check_header(dev_handle, n_blocks - 1, b_size, gpt->raw_data); 86 99 if (rc == EBADCHECKSUM || rc == EINVAL) { 87 100 errno = rc; … … 90 103 } 91 104 105 gpt->device = dev_handle; 106 92 107 return gpt; 93 108 … … 103 118 * @return 0 on success, libblock error code otherwise 104 119 */ 105 int gpt_write_gpt_header(gpt_t * header, service_id_t dev_handle)120 int gpt_write_gpt_header(gpt_t * gpt, service_id_t dev_handle) 106 121 { 107 122 int rc; 108 123 size_t b_size; 109 124 110 header->raw_data->header_crc32 = 0; 111 header->raw_data->header_crc32 = compute_crc32(header, header->header_size); 125 gpt->raw_data->header_crc32 = 0; 126 gpt->raw_data->header_crc32 = compute_crc32((uint8_t *) gpt->raw_data, 127 uint32_t_le2host(gpt->raw_data->header_size)); 112 128 113 129 rc = block_get_bsize(dev_handle, &b_size); … … 120 136 121 137 /* Write to main GPT header location */ 122 rc = block_write_direct(dev_handle, GPT_HDR_BA, GPT_HDR_BS, header->raw_data);138 rc = block_write_direct(dev_handle, GPT_HDR_BA, GPT_HDR_BS, gpt->raw_data); 123 139 if (rc != EOK) 124 140 block_fini(dev_handle); … … 131 147 132 148 /* Write to backup GPT header location */ 133 rc = block_write_direct(dev_handle, n_blocks - 1, GPT_HDR_BS, header->raw_data); 149 //FIXME: those idiots thought it would be cool to have these fields in reverse order... 150 rc = block_write_direct(dev_handle, n_blocks - 1, GPT_HDR_BS, gpt->raw_data); 134 151 block_fini(dev_handle); 135 152 if (rc != EOK) … … 147 164 gpt_parts_t * gpt_read_partitions(gpt_t * gpt) 148 165 { 149 int i; 166 int rc; 167 unsigned int i; 150 168 gpt_parts_t * res; 151 uint32_t num_ent = uint32_t_le2host(gpt-> header.num_entries);152 uint32_t ent_size = uint32_t_le2host(gpt-> header.entry_size);153 uint64_t ent_lba = uint64_t_le2host(gpt-> header.entry_lba);169 uint32_t num_ent = uint32_t_le2host(gpt->raw_data->num_entries); 170 uint32_t ent_size = uint32_t_le2host(gpt->raw_data->entry_size); 171 uint64_t ent_lba = uint64_t_le2host(gpt->raw_data->entry_lba); 154 172 155 173 res = alloc_part_array(num_ent); … … 162 180 * - we don't need more bytes 163 181 * - the size of GPT partition entry can be different to 128 bytes */ 164 rc = block_init(EXCHANGE_SERIALIZE, dev_handle, sizeof(gpt_entry_t));182 rc = block_init(EXCHANGE_SERIALIZE, gpt->device, sizeof(gpt_entry_t)); 165 183 if (rc != EOK) { 166 184 gpt_free_partitions(res); … … 200 218 } 201 219 202 uint32_t crc = compute_crc32(res->part_array, res->num_ent * sizeof(gpt_entry_t)); 203 204 if(gpt->raw_data.pe_array_crc32 != crc) 220 /* FIXME: so far my boasting about variable partition entry size 221 * will not work. The CRC32 checksums will be different. 222 * This can't be fixed easily - we'd have to run the checksum 223 * on all of the partition entry array. 224 */ 225 uint32_t crc = compute_crc32((uint8_t *) res->part_array, res->num_ent * sizeof(gpt_entry_t)); 226 227 if(uint32_t_le2host(gpt->raw_data->pe_array_crc32) != crc) 205 228 { 206 229 gpt_free_partitions(res); … … 214 237 /** Write GPT and partitions to device 215 238 * @param parts partition list to be written 216 * @param mbr MBR to be written with'parts' partitions239 * @param header GPT header belonging to the 'parts' partitions 217 240 * @param dev_handle device to write the data to 218 241 * 219 242 * @return returns EOK on succes, specific error code otherwise 220 243 */ 221 int gpt_write_partitions(gpt_parts_t * parts, gpt_t * header, service_id_t dev_handle)222 { 223 int i;244 int gpt_write_partitions(gpt_parts_t * parts, gpt_t * gpt, service_id_t dev_handle) 245 { 246 int rc; 224 247 size_t b_size; 225 248 226 header->raw_data->pe_array_crc32 = compute_crc32(parts->part_array, parts->num_ent * header->raw_data->entry_size);249 gpt->raw_data->pe_array_crc32 = compute_crc32((uint8_t *) parts->part_array, parts->num_ent * gpt->raw_data->entry_size); 227 250 228 251 rc = block_get_bsize(dev_handle, &b_size); … … 235 258 236 259 /* Write to main GPT partition array location */ 237 rc = block_write_direct(dev_handle, uint64_t_le2host( header->entry_lba),238 nearest_larger_int((uint64_t_le2host( header->raw_data->entry_size) * parts->num_ent) / b_size),260 rc = block_write_direct(dev_handle, uint64_t_le2host(gpt->raw_data->entry_lba), 261 nearest_larger_int((uint64_t_le2host(gpt->raw_data->entry_size) * parts->num_ent) / b_size), 239 262 parts->part_array); 240 263 if (rc != EOK) … … 254 277 255 278 256 gpt_write_gpt_header( header, dev_handle);279 gpt_write_gpt_header(gpt, dev_handle); 257 280 258 281 return 0; 282 283 } 284 285 gpt_parts_t * gpt_add_partition(gpt_parts_t * parts, g_part_t * partition) 286 { 287 288 } 289 290 gpt_parts_t * gpt_remove_partition(gpt_parts_t * parts, int idx) 291 { 259 292 260 293 } … … 263 296 void gpt_free_gpt(gpt_t * gpt) 264 297 { 265 free(gpt-> header_lba);298 free(gpt->raw_data); 266 299 free(gpt); 267 300 } … … 286 319 { 287 320 /* Beware: first 3 blocks are byteswapped! */ 288 p->raw_data.part_type[3] = gpt_ptypes[type] [0];289 p->raw_data.part_type[2] = gpt_ptypes[type] [1];290 p->raw_data.part_type[1] = gpt_ptypes[type] [2];291 p->raw_data.part_type[0] = gpt_ptypes[type] [3];292 293 p->raw_data.part_type[5] = gpt_ptypes[type] [4];294 p->raw_data.part_type[4] = gpt_ptypes[type] [5];295 296 p->raw_data.part_type[7] = gpt_ptypes[type] [6];297 p->raw_data.part_type[6] = gpt_ptypes[type] [7];298 299 p->raw_data.part_type[8] = gpt_ptypes[type] [8];300 p->raw_data.part_type[9] = gpt_ptypes[type] [9];301 p->raw_data.part_type[10] = gpt_ptypes[type] [10];302 p->raw_data.part_type[11] = gpt_ptypes[type] [11];303 p->raw_data.part_type[12] = gpt_ptypes[type] [12];304 p->raw_data.part_type[13] = gpt_ptypes[type] [13];305 p->raw_data.part_type[14] = gpt_ptypes[type] [14];306 p->raw_data.part_type[15] = gpt_ptypes[type] [15];321 p->raw_data.part_type[3] = gpt_ptypes[type].guid[0]; 322 p->raw_data.part_type[2] = gpt_ptypes[type].guid[1]; 323 p->raw_data.part_type[1] = gpt_ptypes[type].guid[2]; 324 p->raw_data.part_type[0] = gpt_ptypes[type].guid[3]; 325 326 p->raw_data.part_type[5] = gpt_ptypes[type].guid[4]; 327 p->raw_data.part_type[4] = gpt_ptypes[type].guid[5]; 328 329 p->raw_data.part_type[7] = gpt_ptypes[type].guid[6]; 330 p->raw_data.part_type[6] = gpt_ptypes[type].guid[7]; 331 332 p->raw_data.part_type[8] = gpt_ptypes[type].guid[8]; 333 p->raw_data.part_type[9] = gpt_ptypes[type].guid[9]; 334 p->raw_data.part_type[10] = gpt_ptypes[type].guid[10]; 335 p->raw_data.part_type[11] = gpt_ptypes[type].guid[11]; 336 p->raw_data.part_type[12] = gpt_ptypes[type].guid[12]; 337 p->raw_data.part_type[13] = gpt_ptypes[type].guid[13]; 338 p->raw_data.part_type[14] = gpt_ptypes[type].guid[14]; 339 p->raw_data.part_type[15] = gpt_ptypes[type].guid[15]; 307 340 } 308 341 309 342 /** Copy partition name */ 310 void gpt_set_part_name(gpt_entry_t * p, char _tname[], size_t length)343 void gpt_set_part_name(gpt_entry_t * p, char * name[], size_t length) 311 344 { 312 345 memcpy(p->part_name, name, length); … … 315 348 // Internal functions follow // 316 349 317 static int load_and_check_header(service_id_t handle, aoff64_t addr, gpt_t * header) 318 { 319 rc = block_init(EXCHANGE_ATOMIC, handle, b_size); 320 if (rc != EOK) 321 return rc; 322 323 rc = block_read_direct(handle, addr, GPT_HDR_BS, gpt->header_lba); 324 block_fini(handle); 325 if (rc != EOK) 326 return rc; 327 328 329 int i; 350 static int load_and_check_header(service_id_t dev_handle, aoff64_t addr, size_t b_size, gpt_header_t * header) 351 { 352 int rc; 353 354 rc = block_init(EXCHANGE_ATOMIC, dev_handle, b_size); 355 if (rc != EOK) 356 return rc; 357 358 rc = block_read_direct(dev_handle, addr, GPT_HDR_BS, header); 359 block_fini(dev_handle); 360 if (rc != EOK) 361 return rc; 362 363 364 unsigned int i; 330 365 /* Check the EFI signature */ 331 366 for (i = 0; i < 8; ++i) { 332 if ( gpt->header_lba.efi_signature[i] != efi_signature[i])367 if (header->efi_signature[i] != efi_signature[i]) 333 368 return EINVAL; 334 369 } 335 370 336 371 /* Check the CRC32 of the header */ 337 uint32_t crc = gpt->header_lba->header_crc32;338 gpt->header_lba->header_crc32 = 0;339 if (crc != compute_crc32( gpt->header_lba, gpt->header_lba->header_size))372 uint32_t crc = header->header_crc32; 373 header->header_crc32 = 0; 374 if (crc != compute_crc32((uint8_t *) header, header->header_size)) 340 375 return EBADCHECKSUM; 341 376 else 342 gpt->header_lba->header_crc32 = crc;377 header->header_crc32 = crc; 343 378 344 379 /* Check for zeroes in the rest of the block */ 345 380 for (i = sizeof(gpt_header_t); i < b_size; ++i) { 346 if (((uint8_t *) gpt->header_lba)[i] != 0) 347 goto EINVAL; 348 } 349 350 gpt->device = dev_handle; 351 //gpt->partitions = NULL; 352 381 if (((uint8_t *) header)[i] != 0) 382 return EINVAL; 383 } 384 353 385 return EOK; 354 386 } … … 364 396 uint32_t size = num > GPT_BASE_PART_NUM ? num : GPT_BASE_PART_NUM; 365 397 res->part_array = malloc(size * sizeof(gpt_entry_t)); 366 if (res .part_array == NULL) {398 if (res->part_array == NULL) { 367 399 free(res); 368 400 errno = ENOMEM; -
uspace/lib/gpt/libgpt.h
rcbd64057 r7570e800 36 36 #define __GPT_H__ 37 37 38 #define NAME "libgpt" 39 38 40 #include <sys/types.h> 39 41 … … 52 54 }; 53 55 54 /** GPT header */ 56 /** GPT header 57 * - all in little endian. 58 */ 55 59 typedef struct { 56 60 uint8_t efi_signature[8]; … … 77 81 service_id_t device; 78 82 /** Linked list of partitions (initially NULL) */ 79 //g_part_t * partitions; //shall we keep this? same problem as in libmbr80 //NOTE: if we have partition list here, do we free() it or not?81 83 } gpt_t; 82 84 … … 109 111 /** Resizable partition array */ 110 112 gpt_entry_t * part_array; 111 112 113 } gpt_parts_t; 113 114 … … 115 116 const char * desc; 116 117 const char * guid; 117 } 118 }; 118 119 119 struct partition_type gpt_ptypes[] {120 struct partition_type gpt_ptypes[] = { 120 121 { "Unused entry", "00000000-0000-0000-0000-000000000000" }, 121 122 { "MBR partition scheme", "024DEE41-33E7-11D3-9D69-0008C781F39F" }, … … 184 185 185 186 extern gpt_t * gpt_read_gpt_header(service_id_t dev_handle); 186 extern int gpt_write_gpt_header(gpt_ header_theader, service_id_t dev_handle);187 extern int gpt_write_gpt_header(gpt_t * header, service_id_t dev_handle); 187 188 188 189 extern gpt_parts_t * gpt_read_partitions(gpt_t * gpt); 189 extern int gpt_write_partitions(gpt_parts_t * parts, gpt_t * header); 190 extern gpt_parts_t * gpt_add_partition(gpt_parts_t * parts, g_part_t partition); 191 extern gpt_parts_t * gpt_remove_partition(gpt_parts_t * parts, int idx); 190 extern int gpt_write_partitions(gpt_parts_t * parts, gpt_t * header, service_id_t dev_handle); 191 extern int gpt_add_partition(gpt_parts_t * parts, g_part_t * partition); 192 extern void gpt_remove_partition(gpt_parts_t * parts, int idx); 193 extern void gpt_set_part_type(g_part_t * p, int type); 194 extern void gpt_set_part_name(gpt_entry_t * p, char * name[], size_t length); 192 195 193 196 extern void gpt_free_gpt(gpt_t * gpt);
Note:
See TracChangeset
for help on using the changeset viewer.