source: mainline/uspace/lib/label/src/gpt.c@ bf7ddde

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since bf7ddde was bf7ddde, checked in by Jiri Svoboda <jiri@…>, 10 years ago

Generate and verify CRCs.

  • Property mode set to 100644
File size: 17.3 KB
Line 
1/*
2 * Copyright (c) 2015 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup liblabel
30 * @{
31 */
32/**
33 * @file GUID Partition Table label.
34 */
35
36#include <adt/checksum.h>
37#include <block.h>
38#include <byteorder.h>
39#include <errno.h>
40#include <mem.h>
41#include <stdlib.h>
42
43#include "std/gpt.h"
44#include "gpt.h"
45
46static int gpt_open(service_id_t, label_t **);
47static int gpt_create(service_id_t, label_t **);
48static void gpt_close(label_t *);
49static int gpt_destroy(label_t *);
50static int gpt_get_info(label_t *, label_info_t *);
51static label_part_t *gpt_part_first(label_t *);
52static label_part_t *gpt_part_next(label_part_t *);
53static void gpt_part_get_info(label_part_t *, label_part_info_t *);
54static int gpt_part_create(label_t *, label_part_spec_t *, label_part_t **);
55static int gpt_part_destroy(label_part_t *);
56
57static void gpt_unused_pte(gpt_entry_t *);
58static int gpt_part_to_pte(label_part_t *, gpt_entry_t *);
59static int gpt_pte_to_part(label_t *, gpt_entry_t *, int);
60static int gpt_pte_update(label_t *, gpt_entry_t *, int);
61
62static int gpt_update_pt_crc(label_t *, uint32_t);
63static void gpt_hdr_compute_crc(gpt_header_t *, size_t);
64static int gpt_hdr_get_crc(gpt_header_t *, size_t, uint32_t *);
65
66const uint8_t efi_signature[8] = {
67 /* "EFI PART" in ASCII */
68 0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54
69};
70
71label_ops_t gpt_label_ops = {
72 .open = gpt_open,
73 .create = gpt_create,
74 .close = gpt_close,
75 .destroy = gpt_destroy,
76 .get_info = gpt_get_info,
77 .part_first = gpt_part_first,
78 .part_next = gpt_part_next,
79 .part_get_info = gpt_part_get_info,
80 .part_create = gpt_part_create,
81 .part_destroy = gpt_part_destroy
82};
83
84static int gpt_open(service_id_t sid, label_t **rlabel)
85{
86 label_t *label = NULL;
87 gpt_header_t *gpt_hdr[2];
88 gpt_entry_t *eptr;
89 uint8_t *etable[2];
90 size_t bsize;
91 uint32_t num_entries;
92 uint32_t esize;
93 uint32_t pt_blocks;
94 uint64_t ptba[2];
95 uint64_t h1ba;
96 uint32_t entry;
97 uint32_t pt_crc;
98 uint64_t ba_min, ba_max;
99 uint32_t hdr_size;
100 uint32_t hdr_crc;
101 int i, j;
102 int rc;
103
104 gpt_hdr[0] = NULL;
105 gpt_hdr[1] = NULL;
106 etable[0] = NULL;
107 etable[1] = NULL;
108
109 rc = block_get_bsize(sid, &bsize);
110 if (rc != EOK) {
111 rc = EIO;
112 goto error;
113 }
114
115 if (bsize < 512 || (bsize % 512) != 0) {
116 rc = EINVAL;
117 goto error;
118 }
119
120 gpt_hdr[0] = calloc(1, bsize);
121 if (gpt_hdr[0] == NULL) {
122 rc = ENOMEM;
123 goto error;
124 }
125
126 gpt_hdr[1] = calloc(1, bsize);
127 if (gpt_hdr[1] == NULL) {
128 rc = ENOMEM;
129 goto error;
130 }
131
132 rc = block_read_direct(sid, gpt_hdr_ba, 1, gpt_hdr[0]);
133 if (rc != EOK) {
134 rc = EIO;
135 goto error;
136 }
137
138 h1ba = uint64_t_le2host(gpt_hdr[0]->alternate_lba);
139
140 rc = block_read_direct(sid, h1ba, 1, gpt_hdr[1]);
141 if (rc != EOK) {
142 rc = EIO;
143 goto error;
144 }
145
146 label = calloc(1, sizeof(label_t));
147 if (label == NULL)
148 return ENOMEM;
149
150 list_initialize(&label->parts);
151
152 for (j = 0; j < 2; j++) {
153 for (i = 0; i < 8; ++i) {
154 if (gpt_hdr[j]->efi_signature[i] != efi_signature[i]) {
155 rc = EINVAL;
156 goto error;
157 }
158 }
159 }
160
161 if (uint32_t_le2host(gpt_hdr[0]->revision) !=
162 uint32_t_le2host(gpt_hdr[1]->revision)) {
163 rc = EINVAL;
164 goto error;
165 }
166
167 if (uint32_t_le2host(gpt_hdr[0]->header_size) !=
168 uint32_t_le2host(gpt_hdr[1]->header_size)) {
169 rc = EINVAL;
170 goto error;
171 }
172
173 hdr_size = uint32_t_le2host(gpt_hdr[0]->header_size);
174 if (hdr_size < sizeof(gpt_header_t) ||
175 hdr_size > bsize) {
176 rc = EINVAL;
177 goto error;
178 }
179
180 for (j = 0; j < 2; j++) {
181 rc = gpt_hdr_get_crc(gpt_hdr[j], hdr_size, &hdr_crc);
182 if (rc != EOK)
183 goto error;
184
185 if (uint32_t_le2host(gpt_hdr[j]->header_crc32) != hdr_crc) {
186 rc = EINVAL;
187 goto error;
188 }
189 }
190
191 if (uint64_t_le2host(gpt_hdr[0]->my_lba) != gpt_hdr_ba) {
192 rc = EINVAL;
193 goto error;
194 }
195
196 if (uint64_t_le2host(gpt_hdr[1]->my_lba) != h1ba) {
197 rc = EINVAL;
198 goto error;
199 }
200
201 if (uint64_t_le2host(gpt_hdr[1]->alternate_lba) != gpt_hdr_ba) {
202 rc = EINVAL;
203 goto error;
204 }
205
206 num_entries = uint32_t_le2host(gpt_hdr[0]->num_entries);
207 esize = uint32_t_le2host(gpt_hdr[0]->entry_size);
208 pt_blocks = (num_entries * esize + bsize - 1) / bsize;
209 ptba[0] = uint64_t_le2host(gpt_hdr[0]->entry_lba);
210 ptba[1] = uint64_t_le2host(gpt_hdr[1]->entry_lba);
211 ba_min = uint64_t_le2host(gpt_hdr[0]->first_usable_lba);
212 ba_max = uint64_t_le2host(gpt_hdr[0]->last_usable_lba);
213 pt_crc = uint32_t_le2host(gpt_hdr[0]->pe_array_crc32);
214
215 if (uint64_t_le2host(gpt_hdr[1]->first_usable_lba) != ba_min) {
216 rc = EINVAL;
217 goto error;
218 }
219
220 if (uint64_t_le2host(gpt_hdr[1]->last_usable_lba) != ba_max) {
221 rc = EINVAL;
222 goto error;
223 }
224
225 for (i = 0; i < 16; i++) {
226 if (gpt_hdr[1]->disk_guid[i] != gpt_hdr[0]->disk_guid[i]) {
227 rc = EINVAL;
228 goto error;
229 }
230 }
231
232 if (uint32_t_le2host(gpt_hdr[1]->num_entries) != num_entries) {
233 rc = EINVAL;
234 goto error;
235 }
236
237 if (uint32_t_le2host(gpt_hdr[1]->entry_size) != esize) {
238 rc = EINVAL;
239 goto error;
240 }
241
242 if (num_entries < 1) {
243 rc = EINVAL;
244 goto error;
245 }
246
247 if (esize < sizeof(gpt_entry_t)) {
248 rc = EINVAL;
249 goto error;
250 }
251
252 if (ba_max < ba_min) {
253 rc = EINVAL;
254 goto error;
255 }
256
257 /* Check fields in backup header for validity */
258
259 for (j = 0; j < 2; j++) {
260 etable[j] = calloc(1, pt_blocks * bsize);
261 if (etable[j] == NULL) {
262 rc = ENOMEM;
263 goto error;
264 }
265
266 rc = block_read_direct(sid, ptba[j], pt_blocks / 2, etable[j]);
267 if (rc != EOK) {
268 rc = EIO;
269 goto error;
270 }
271
272 if (compute_crc32(etable[j], num_entries * esize) != pt_crc) {
273 rc = EIO;
274 goto error;
275 }
276
277 for (entry = 0; entry < num_entries; entry++) {
278 eptr = (gpt_entry_t *)(etable[j] + entry * esize);
279 rc = gpt_pte_to_part(label, eptr, entry + 1);
280 if (rc != EOK)
281 goto error;
282 }
283 }
284
285 free(etable[0]);
286 etable[0] = NULL;
287 free(etable[1]);
288 etable[1] = NULL;
289 free(gpt_hdr[0]);
290 gpt_hdr[0] = NULL;
291 free(gpt_hdr[1]);
292 gpt_hdr[1] = NULL;
293
294 label->ops = &gpt_label_ops;
295 label->ltype = lt_gpt;
296 label->svc_id = sid;
297 label->ablock0 = ba_min;
298 label->anblocks = ba_max - ba_min + 1;
299 label->pri_entries = num_entries;
300 label->block_size = bsize;
301
302 label->lt.gpt.hdr_ba[0] = gpt_hdr_ba;
303 label->lt.gpt.hdr_ba[1] = h1ba;
304 label->lt.gpt.ptable_ba[0] = ptba[0];
305 label->lt.gpt.ptable_ba[1] = ptba[1];
306 label->lt.gpt.esize = esize;
307 label->lt.gpt.pt_blocks = pt_blocks;
308 label->lt.gpt.pt_crc = pt_crc;
309 label->lt.gpt.hdr_size = hdr_size;
310
311 *rlabel = label;
312 return EOK;
313error:
314 free(etable[0]);
315 free(etable[1]);
316 free(gpt_hdr[0]);
317 free(gpt_hdr[1]);
318 free(label);
319 return rc;
320}
321
322static int gpt_create(service_id_t sid, label_t **rlabel)
323{
324 label_t *label = NULL;
325 gpt_header_t *gpt_hdr = NULL;
326 uint8_t *etable = NULL;
327 size_t bsize;
328 uint32_t num_entries;
329 uint32_t esize;
330 uint64_t ptba[2];
331 uint64_t hdr_ba[2];
332 uint64_t pt_blocks;
333 uint64_t ba_min, ba_max;
334 aoff64_t nblocks;
335 uint64_t resv_blocks;
336 uint32_t pt_crc;
337 int i, j;
338 int rc;
339
340 rc = block_get_bsize(sid, &bsize);
341 if (rc != EOK) {
342 rc = EIO;
343 goto error;
344 }
345
346 if (bsize < 512 || (bsize % 512) != 0) {
347 rc = EINVAL;
348 goto error;
349 }
350
351 rc = block_get_nblocks(sid, &nblocks);
352 if (rc != EOK) {
353 rc = EIO;
354 goto error;
355 }
356
357 /* Number of blocks of a partition table */
358 pt_blocks = gpt_ptable_min_size / bsize;
359 /* Minimum number of reserved (not allocatable) blocks */
360 resv_blocks = 3 + 2 * pt_blocks;
361
362 if (nblocks <= resv_blocks) {
363 rc = ENOSPC;
364 goto error;
365 }
366
367 hdr_ba[0] = gpt_hdr_ba;
368 hdr_ba[1] = nblocks - 1;
369 ptba[0] = 2;
370 ptba[1] = nblocks - 1 - pt_blocks;
371 ba_min = ptba[0] + pt_blocks;
372 ba_max = ptba[1] - 1;
373 esize = sizeof(gpt_entry_t);
374
375 num_entries = pt_blocks * bsize / sizeof(gpt_entry_t);
376
377 for (i = 0; i < 2; i++) {
378 etable = calloc(1, pt_blocks * bsize);
379 if (etable == NULL) {
380 rc = ENOMEM;
381 goto error;
382 }
383
384 rc = block_write_direct(sid, ptba[i], pt_blocks, etable);
385 if (rc != EOK) {
386 rc = EIO;
387 goto error;
388 }
389
390 pt_crc = compute_crc32((uint8_t *)etable,
391 num_entries * esize);
392
393 free(etable);
394 etable = NULL;
395
396 gpt_hdr = calloc(1, bsize);
397 if (gpt_hdr == NULL) {
398 rc = ENOMEM;
399 goto error;
400 }
401
402 for (j = 0; j < 8; ++j)
403 gpt_hdr->efi_signature[j] = efi_signature[j];
404 gpt_hdr->revision = host2uint32_t_le(gpt_revision);
405 gpt_hdr->header_size = host2uint32_t_le(sizeof(gpt_header_t));
406 gpt_hdr->header_crc32 = 0;
407 gpt_hdr->my_lba = host2uint64_t_le(hdr_ba[i]);
408 gpt_hdr->alternate_lba = host2uint64_t_le(hdr_ba[1 - i]);
409 gpt_hdr->first_usable_lba = host2uint64_t_le(ba_min);
410 gpt_hdr->last_usable_lba = host2uint64_t_le(ba_max);
411 //gpt_hdr->disk_guid XXX
412 gpt_hdr->entry_lba = host2uint64_t_le(ptba[i]);
413 gpt_hdr->num_entries = host2uint32_t_le(num_entries);
414 gpt_hdr->entry_size = host2uint32_t_le(esize);
415 gpt_hdr->pe_array_crc32 = pt_crc;
416
417 gpt_hdr_compute_crc(gpt_hdr, sizeof(gpt_header_t));
418
419 rc = block_write_direct(sid, hdr_ba[i], 1, gpt_hdr);
420 if (rc != EOK) {
421 rc = EIO;
422 goto error;
423 }
424
425 free(gpt_hdr);
426 gpt_hdr = NULL;
427 }
428
429 label = calloc(1, sizeof(label_t));
430 if (label == NULL)
431 return ENOMEM;
432
433 list_initialize(&label->parts);
434
435 label->ops = &gpt_label_ops;
436 label->ltype = lt_gpt;
437 label->svc_id = sid;
438 label->ablock0 = ba_min;
439 label->anblocks = ba_max - ba_min + 1;
440 label->pri_entries = num_entries;
441 label->block_size = bsize;
442
443 label->lt.gpt.hdr_ba[0] = hdr_ba[0];
444 label->lt.gpt.hdr_ba[1] = hdr_ba[1];
445 label->lt.gpt.ptable_ba[0] = ptba[0];
446 label->lt.gpt.ptable_ba[1] = ptba[1];
447 label->lt.gpt.esize = esize;
448 label->lt.gpt.pt_blocks = pt_blocks;
449 label->lt.gpt.hdr_size = sizeof(gpt_header_t);
450
451 *rlabel = label;
452 return EOK;
453error:
454 free(etable);
455 free(gpt_hdr);
456 free(label);
457 return rc;
458}
459
460static void gpt_close(label_t *label)
461{
462 label_part_t *part;
463
464 part = gpt_part_first(label);
465 while (part != NULL) {
466 list_remove(&part->llabel);
467 free(part);
468 part = gpt_part_first(label);
469 }
470
471 free(label);
472}
473
474static int gpt_destroy(label_t *label)
475{
476 gpt_header_t *gpt_hdr = NULL;
477 uint8_t *etable = NULL;
478 label_part_t *part;
479 int i;
480 int rc;
481
482 part = gpt_part_first(label);
483 if (part != NULL) {
484 rc = ENOTEMPTY;
485 goto error;
486 }
487
488 for (i = 0; i < 2; i++) {
489 gpt_hdr = calloc(1, label->block_size);
490 if (gpt_hdr == NULL) {
491 rc = ENOMEM;
492 goto error;
493 }
494
495 rc = block_write_direct(label->svc_id, label->lt.gpt.hdr_ba[i],
496 1, gpt_hdr);
497 if (rc != EOK) {
498 rc = EIO;
499 goto error;
500 }
501
502 free(gpt_hdr);
503 gpt_hdr = NULL;
504
505 etable = calloc(1, label->lt.gpt.pt_blocks *
506 label->block_size);
507 if (etable == NULL) {
508 rc = ENOMEM;
509 goto error;
510 }
511
512 rc = block_write_direct(label->svc_id,
513 label->lt.gpt.ptable_ba[i], label->lt.gpt.pt_blocks,
514 etable);
515 if (rc != EOK) {
516 rc = EIO;
517 goto error;
518 }
519
520 free(etable);
521 etable = 0;
522 }
523
524 free(label);
525 return EOK;
526error:
527 return rc;
528}
529
530static int gpt_get_info(label_t *label, label_info_t *linfo)
531{
532 memset(linfo, 0, sizeof(label_info_t));
533 linfo->dcnt = dc_label;
534 linfo->ltype = lt_gpt;
535 linfo->ablock0 = label->ablock0;
536 linfo->anblocks = label->anblocks;
537 return EOK;
538}
539
540static label_part_t *gpt_part_first(label_t *label)
541{
542 link_t *link;
543
544 link = list_first(&label->parts);
545 if (link == NULL)
546 return NULL;
547
548 return list_get_instance(link, label_part_t, llabel);
549}
550
551static label_part_t *gpt_part_next(label_part_t *part)
552{
553 link_t *link;
554
555 link = list_next(&part->llabel, &part->label->parts);
556 if (link == NULL)
557 return NULL;
558
559 return list_get_instance(link, label_part_t, llabel);
560}
561
562static void gpt_part_get_info(label_part_t *part, label_part_info_t *pinfo)
563{
564 pinfo->index = part->index;
565 pinfo->block0 = part->block0;
566 pinfo->nblocks = part->nblocks;
567}
568
569static int gpt_part_create(label_t *label, label_part_spec_t *pspec,
570 label_part_t **rpart)
571{
572 label_part_t *part;
573 gpt_entry_t pte;
574 int rc;
575
576 part = calloc(1, sizeof(label_part_t));
577 if (part == NULL) {
578 rc = ENOMEM;
579 goto error;
580 }
581
582 /* XXX Verify index, block0, nblocks */
583
584 if (pspec->index < 1 || pspec->index > label->pri_entries) {
585 rc = EINVAL;
586 goto error;
587 }
588
589 /* XXX Check if index is used */
590
591 part->label = label;
592 part->index = pspec->index;
593 part->block0 = pspec->block0;
594 part->nblocks = pspec->nblocks;
595 part->ptype = pspec->ptype;
596
597 /* Prepare partition table entry */
598 rc = gpt_part_to_pte(part, &pte);
599 if (rc != EOK) {
600 rc = EINVAL;
601 goto error;
602 }
603
604 /* Modify partition tables */
605 rc = gpt_pte_update(label, &pte, pspec->index - 1);
606 if (rc != EOK) {
607 rc = EIO;
608 goto error;
609 }
610
611 list_append(&part->llabel, &label->parts);
612
613 *rpart = part;
614 return EOK;
615error:
616 free(part);
617 return rc;
618}
619
620static int gpt_part_destroy(label_part_t *part)
621{
622 gpt_entry_t pte;
623 int rc;
624
625 /* Prepare unused partition table entry */
626 gpt_unused_pte(&pte);
627
628 /* Modify partition tables */
629 rc = gpt_pte_update(part->label, &pte, part->index - 1);
630 if (rc != EOK)
631 return EIO;
632
633 list_remove(&part->llabel);
634 free(part);
635 return EOK;
636}
637
638static void gpt_unused_pte(gpt_entry_t *pte)
639{
640 memset(pte, 0, sizeof(gpt_entry_t));
641}
642
643static int gpt_part_to_pte(label_part_t *part, gpt_entry_t *pte)
644{
645 uint64_t eblock;
646
647 eblock = part->block0 + part->nblocks - 1;
648 if (eblock < part->block0)
649 return EINVAL;
650
651 memset(pte, 0, sizeof(gpt_entry_t));
652 pte->part_type[0] = 0x12;
653 pte->part_id[0] = 0x34;
654 pte->start_lba = host2uint64_t_le(part->block0);
655 pte->end_lba = host2uint64_t_le(eblock);
656// pte->attributes
657// pte->part_name
658 return EOK;
659}
660
661static int gpt_pte_to_part(label_t *label, gpt_entry_t *pte, int index)
662{
663 label_part_t *part;
664 bool present;
665 uint64_t b0, b1;
666 int i;
667
668 present = false;
669 for (i = 0; i < 8; i++)
670 if (pte->part_type[i] != 0x00)
671 present = true;
672
673 if (!present)
674 return EOK;
675
676 part = calloc(1, sizeof(label_part_t));
677 if (part == NULL)
678 return ENOMEM;
679
680 b0 = uint64_t_le2host(pte->start_lba);
681 b1 = uint64_t_le2host(pte->end_lba);
682 if (b1 <= b0)
683 return EINVAL;
684
685 part->index = index;
686 part->block0 = b0;
687 part->nblocks = b1 - b0 + 1;
688
689 part->label = label;
690 list_append(&part->llabel, &label->parts);
691 return EOK;
692}
693
694/** Update partition table entry at specified index.
695 *
696 * Replace partition entry at index @a index with the contents of
697 * @a pte.
698 */
699static int gpt_pte_update(label_t *label, gpt_entry_t *pte, int index)
700{
701 size_t pos;
702 uint64_t ba;
703 uint64_t nblocks;
704 size_t ptbytes;
705 uint8_t *buf;
706 gpt_entry_t *e;
707 uint32_t crc;
708 int i;
709 int rc;
710
711 /* Byte offset of partition entry */
712 pos = index * label->lt.gpt.esize;
713 /* Number of bytes in partition table */
714 ptbytes = label->pri_entries * label->lt.gpt.esize;
715
716 buf = calloc(1, label->block_size * label->lt.gpt.pt_blocks);
717 if (buf == NULL)
718 return ENOMEM;
719
720 /* For both partition tables: read, modify, write */
721 for (i = 0; i < 2; i++) {
722 ba = label->lt.gpt.ptable_ba[i];
723 nblocks = label->lt.gpt.pt_blocks;
724
725 rc = block_read_direct(label->svc_id, ba, nblocks, buf);
726 if (rc != EOK) {
727 rc = EIO;
728 goto error;
729 }
730
731 crc = compute_crc32(buf, ptbytes);
732 if (crc != label->lt.gpt.pt_crc) {
733 /* Corruption detected */
734 rc = EIO;
735 goto error;
736 }
737
738 /* Replace single entry */
739 e = (gpt_entry_t *)(&buf[pos]);
740 *e = *pte;
741
742 rc = block_write_direct(label->svc_id, ba, nblocks, buf);
743 if (rc != EOK) {
744 rc = EIO;
745 goto error;
746 }
747
748 crc = compute_crc32(buf, ptbytes);
749 rc = gpt_update_pt_crc(label, crc);
750 if (rc != EOK) {
751 rc = EIO;
752 goto error;
753 }
754 }
755
756 free(buf);
757 return EOK;
758error:
759 free(buf);
760 return rc;
761}
762
763static int gpt_update_pt_crc(label_t *label, uint32_t crc)
764{
765 gpt_header_t *gpt_hdr;
766 int rc;
767 int i;
768
769 gpt_hdr = calloc(1, label->block_size);
770 if (gpt_hdr == NULL) {
771 rc = ENOMEM;
772 goto error;
773 }
774
775 for (i = 0; i < 2; i++) {
776 rc = block_read_direct(label->svc_id,
777 label->lt.gpt.hdr_ba[i], 1, gpt_hdr);
778 if (rc != EOK) {
779 rc = EIO;
780 goto error;
781 }
782
783 gpt_hdr->pe_array_crc32 = host2uint32_t_le(crc);
784 gpt_hdr_compute_crc(gpt_hdr, label->lt.gpt.hdr_size);
785
786 rc = block_write_direct(label->svc_id,
787 label->lt.gpt.hdr_ba[i], 1, gpt_hdr);
788 if (rc != EOK) {
789 rc = EIO;
790 goto error;
791 }
792 }
793
794 free(gpt_hdr);
795 return EOK;
796error:
797 return rc;
798}
799
800static void gpt_hdr_compute_crc(gpt_header_t *hdr, size_t hdr_size)
801{
802 uint32_t crc;
803
804 hdr->header_crc32 = 0;
805 crc = compute_crc32((uint8_t *)hdr, hdr_size);
806 hdr->header_crc32 = crc;
807}
808
809static int gpt_hdr_get_crc(gpt_header_t *hdr, size_t hdr_size, uint32_t *crc)
810{
811 gpt_header_t *c;
812
813 c = calloc(1, sizeof(gpt_header_t));
814 if (c == NULL)
815 return ENOMEM;
816
817 memcpy(c, hdr, hdr_size);
818 c->header_crc32 = 0;
819 *crc = compute_crc32((uint8_t *)c, hdr_size);
820 free(c);
821
822 return EOK;
823}
824
825/** @}
826 */
Note: See TracBrowser for help on using the repository browser.