HelenOS sources
This source file includes following definitions.
- gpt_open
- gpt_create
- gpt_close
- gpt_destroy
- gpt_can_create_pri
- gpt_can_delete_part
- gpt_can_modify_part
- gpt_get_info
- gpt_part_first
- gpt_part_next
- gpt_part_get_info
- gpt_part_create
- gpt_part_destroy
- gpt_suggest_ptype
- gpt_check_free_idx
- gpt_overlap
- gpt_check_free_range
- gpt_unused_pte
- gpt_part_to_pte
- gpt_pte_to_part
- gpt_pte_update
- gpt_update_pt_crc
- gpt_hdr_compute_crc
- gpt_hdr_get_crc
- gpt_pmbr_create
- gpt_pmbr_destroy
#include <adt/checksum.h>
#include <byteorder.h>
#include <errno.h>
#include <mem.h>
#include <stdint.h>
#include <stdlib.h>
#include <uuid.h>
#include "std/mbr.h"
#include "std/gpt.h"
#include "gpt.h"
static errno_t gpt_open(label_bd_t *, label_t **);
static errno_t gpt_create(label_bd_t *, label_t **);
static void gpt_close(label_t *);
static errno_t gpt_destroy(label_t *);
static errno_t gpt_get_info(label_t *, label_info_t *);
static label_part_t *gpt_part_first(label_t *);
static label_part_t *gpt_part_next(label_part_t *);
static void gpt_part_get_info(label_part_t *, label_part_info_t *);
static errno_t gpt_part_create(label_t *, label_part_spec_t *, label_part_t **);
static errno_t gpt_part_destroy(label_part_t *);
static errno_t gpt_suggest_ptype(label_t *, label_pcnt_t, label_ptype_t *);
static errno_t gpt_check_free_idx(label_t *, int);
static errno_t gpt_check_free_range(label_t *, uint64_t, uint64_t);
static void gpt_unused_pte(gpt_entry_t *);
static errno_t gpt_part_to_pte(label_part_t *, gpt_entry_t *);
static errno_t gpt_pte_to_part(label_t *, gpt_entry_t *, int);
static errno_t gpt_pte_update(label_t *, gpt_entry_t *, int);
static errno_t gpt_update_pt_crc(label_t *, uint32_t);
static void gpt_hdr_compute_crc(gpt_header_t *, size_t);
static errno_t gpt_hdr_get_crc(gpt_header_t *, size_t, uint32_t *);
static errno_t gpt_pmbr_create(label_bd_t *, size_t, uint64_t);
static errno_t gpt_pmbr_destroy(label_bd_t *, size_t);
const uint8_t efi_signature[8] = {
0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54
};
label_ops_t gpt_label_ops = {
.open = gpt_open,
.create = gpt_create,
.close = gpt_close,
.destroy = gpt_destroy,
.get_info = gpt_get_info,
.part_first = gpt_part_first,
.part_next = gpt_part_next,
.part_get_info = gpt_part_get_info,
.part_create = gpt_part_create,
.part_destroy = gpt_part_destroy,
.suggest_ptype = gpt_suggest_ptype
};
static errno_t gpt_open(label_bd_t *bd, label_t **rlabel)
{
label_t *label = NULL;
gpt_header_t *gpt_hdr[2];
gpt_entry_t *eptr;
uint8_t *etable[2];
size_t bsize;
aoff64_t nblocks;
uint32_t num_entries;
uint32_t esize;
uint32_t pt_blocks;
uint64_t ptba[2];
uint64_t h1ba;
uint32_t entry;
uint32_t pt_crc;
uint64_t ba_min, ba_max;
uint32_t hdr_size;
uint32_t hdr_crc;
int i, j;
errno_t rc;
gpt_hdr[0] = NULL;
gpt_hdr[1] = NULL;
etable[0] = NULL;
etable[1] = NULL;
rc = bd->ops->get_bsize(bd->arg, &bsize);
if (rc != EOK) {
rc = EIO;
goto error;
}
rc = bd->ops->get_nblocks(bd->arg, &nblocks);
if (rc != EOK) {
rc = EIO;
goto error;
}
if (bsize < 512 || (bsize % 512) != 0) {
rc = EINVAL;
goto error;
}
gpt_hdr[0] = calloc(1, bsize);
if (gpt_hdr[0] == NULL) {
rc = ENOMEM;
goto error;
}
gpt_hdr[1] = calloc(1, bsize);
if (gpt_hdr[1] == NULL) {
rc = ENOMEM;
goto error;
}
rc = bd->ops->read(bd->arg, gpt_hdr_ba, 1, gpt_hdr[0]);
if (rc != EOK) {
rc = EIO;
goto error;
}
h1ba = uint64_t_le2host(gpt_hdr[0]->alternate_lba);
if (h1ba >= nblocks) {
rc = EINVAL;
goto error;
}
rc = bd->ops->read(bd->arg, h1ba, 1, gpt_hdr[1]);
if (rc != EOK) {
rc = EIO;
goto error;
}
label = calloc(1, sizeof(label_t));
if (label == NULL)
return ENOMEM;
list_initialize(&label->parts);
list_initialize(&label->pri_parts);
list_initialize(&label->log_parts);
for (j = 0; j < 2; j++) {
for (i = 0; i < 8; ++i) {
if (gpt_hdr[j]->efi_signature[i] != efi_signature[i]) {
rc = EINVAL;
goto error;
}
}
}
if (uint32_t_le2host(gpt_hdr[0]->revision) !=
uint32_t_le2host(gpt_hdr[1]->revision)) {
rc = EINVAL;
goto error;
}
if (uint32_t_le2host(gpt_hdr[0]->header_size) !=
uint32_t_le2host(gpt_hdr[1]->header_size)) {
rc = EINVAL;
goto error;
}
hdr_size = uint32_t_le2host(gpt_hdr[0]->header_size);
if (hdr_size < sizeof(gpt_header_t) ||
hdr_size > bsize) {
rc = EINVAL;
goto error;
}
for (j = 0; j < 2; j++) {
rc = gpt_hdr_get_crc(gpt_hdr[j], hdr_size, &hdr_crc);
if (rc != EOK)
goto error;
if (uint32_t_le2host(gpt_hdr[j]->header_crc32) != hdr_crc) {
rc = EINVAL;
goto error;
}
}
if (uint64_t_le2host(gpt_hdr[0]->my_lba) != gpt_hdr_ba) {
rc = EINVAL;
goto error;
}
if (uint64_t_le2host(gpt_hdr[1]->my_lba) != h1ba) {
rc = EINVAL;
goto error;
}
if (uint64_t_le2host(gpt_hdr[1]->alternate_lba) != gpt_hdr_ba) {
rc = EINVAL;
goto error;
}
num_entries = uint32_t_le2host(gpt_hdr[0]->num_entries);
esize = uint32_t_le2host(gpt_hdr[0]->entry_size);
pt_blocks = (num_entries * esize + bsize - 1) / bsize;
ptba[0] = uint64_t_le2host(gpt_hdr[0]->entry_lba);
ptba[1] = uint64_t_le2host(gpt_hdr[1]->entry_lba);
ba_min = uint64_t_le2host(gpt_hdr[0]->first_usable_lba);
ba_max = uint64_t_le2host(gpt_hdr[0]->last_usable_lba);
pt_crc = uint32_t_le2host(gpt_hdr[0]->pe_array_crc32);
if (uint64_t_le2host(gpt_hdr[1]->first_usable_lba) != ba_min) {
rc = EINVAL;
goto error;
}
if (uint64_t_le2host(gpt_hdr[1]->last_usable_lba) != ba_max) {
rc = EINVAL;
goto error;
}
for (i = 0; i < 16; i++) {
if (gpt_hdr[1]->disk_guid[i] != gpt_hdr[0]->disk_guid[i]) {
rc = EINVAL;
goto error;
}
}
if (uint32_t_le2host(gpt_hdr[1]->num_entries) != num_entries) {
rc = EINVAL;
goto error;
}
if (uint32_t_le2host(gpt_hdr[1]->entry_size) != esize) {
rc = EINVAL;
goto error;
}
if (num_entries < 1) {
rc = EINVAL;
goto error;
}
if (esize < sizeof(gpt_entry_t)) {
rc = EINVAL;
goto error;
}
if (ba_max < ba_min) {
rc = EINVAL;
goto error;
}
for (j = 0; j < 2; j++) {
etable[j] = calloc(1, pt_blocks * bsize);
if (etable[j] == NULL) {
rc = ENOMEM;
goto error;
}
rc = bd->ops->read(bd->arg, ptba[j], pt_blocks / 2, etable[j]);
if (rc != EOK) {
rc = EIO;
goto error;
}
if (compute_crc32(etable[j], num_entries * esize) != pt_crc) {
rc = EIO;
goto error;
}
}
for (entry = 0; entry < num_entries; entry++) {
eptr = (gpt_entry_t *)(etable[0] + entry * esize);
rc = gpt_pte_to_part(label, eptr, entry + 1);
if (rc != EOK)
goto error;
}
free(etable[0]);
etable[0] = NULL;
free(etable[1]);
etable[1] = NULL;
free(gpt_hdr[0]);
gpt_hdr[0] = NULL;
free(gpt_hdr[1]);
gpt_hdr[1] = NULL;
label->ops = &gpt_label_ops;
label->ltype = lt_gpt;
label->bd = *bd;
label->ablock0 = ba_min;
label->anblocks = ba_max - ba_min + 1;
label->pri_entries = num_entries;
label->block_size = bsize;
label->lt.gpt.hdr_ba[0] = gpt_hdr_ba;
label->lt.gpt.hdr_ba[1] = h1ba;
label->lt.gpt.ptable_ba[0] = ptba[0];
label->lt.gpt.ptable_ba[1] = ptba[1];
label->lt.gpt.esize = esize;
label->lt.gpt.pt_blocks = pt_blocks;
label->lt.gpt.pt_crc = pt_crc;
label->lt.gpt.hdr_size = hdr_size;
*rlabel = label;
return EOK;
error:
free(etable[0]);
free(etable[1]);
free(gpt_hdr[0]);
free(gpt_hdr[1]);
free(label);
return rc;
}
static errno_t gpt_create(label_bd_t *bd, label_t **rlabel)
{
label_t *label = NULL;
gpt_header_t *gpt_hdr = NULL;
uint8_t *etable = NULL;
size_t bsize;
uint32_t num_entries;
uint32_t esize;
uint64_t ptba[2];
uint64_t hdr_ba[2];
uint64_t pt_blocks;
uint64_t ba_min, ba_max;
aoff64_t nblocks;
uint64_t resv_blocks;
uint32_t pt_crc;
uuid_t disk_uuid;
int i, j;
errno_t rc;
rc = bd->ops->get_bsize(bd->arg, &bsize);
if (rc != EOK) {
rc = EIO;
goto error;
}
if (bsize < 512 || (bsize % 512) != 0) {
rc = EINVAL;
goto error;
}
rc = bd->ops->get_nblocks(bd->arg, &nblocks);
if (rc != EOK) {
rc = EIO;
goto error;
}
pt_blocks = gpt_ptable_min_size / bsize;
resv_blocks = 3 + 2 * pt_blocks;
if (nblocks <= resv_blocks) {
rc = ENOSPC;
goto error;
}
rc = gpt_pmbr_create(bd, bsize, nblocks);
if (rc != EOK) {
rc = EIO;
goto error;
}
uuid_generate(&disk_uuid);
hdr_ba[0] = gpt_hdr_ba;
hdr_ba[1] = nblocks - 1;
ptba[0] = 2;
ptba[1] = nblocks - 1 - pt_blocks;
ba_min = ptba[0] + pt_blocks;
ba_max = ptba[1] - 1;
esize = sizeof(gpt_entry_t);
num_entries = pt_blocks * bsize / sizeof(gpt_entry_t);
for (i = 0; i < 2; i++) {
etable = calloc(1, pt_blocks * bsize);
if (etable == NULL) {
rc = ENOMEM;
goto error;
}
rc = bd->ops->write(bd->arg, ptba[i], pt_blocks, etable);
if (rc != EOK) {
rc = EIO;
goto error;
}
pt_crc = compute_crc32((uint8_t *)etable,
num_entries * esize);
free(etable);
etable = NULL;
gpt_hdr = calloc(1, bsize);
if (gpt_hdr == NULL) {
rc = ENOMEM;
goto error;
}
for (j = 0; j < 8; ++j)
gpt_hdr->efi_signature[j] = efi_signature[j];
gpt_hdr->revision = host2uint32_t_le(gpt_revision);
gpt_hdr->header_size = host2uint32_t_le(sizeof(gpt_header_t));
gpt_hdr->header_crc32 = 0;
gpt_hdr->my_lba = host2uint64_t_le(hdr_ba[i]);
gpt_hdr->alternate_lba = host2uint64_t_le(hdr_ba[1 - i]);
gpt_hdr->first_usable_lba = host2uint64_t_le(ba_min);
gpt_hdr->last_usable_lba = host2uint64_t_le(ba_max);
uuid_encode_le(&disk_uuid, gpt_hdr->disk_guid);
gpt_hdr->entry_lba = host2uint64_t_le(ptba[i]);
gpt_hdr->num_entries = host2uint32_t_le(num_entries);
gpt_hdr->entry_size = host2uint32_t_le(esize);
gpt_hdr->pe_array_crc32 = pt_crc;
gpt_hdr_compute_crc(gpt_hdr, sizeof(gpt_header_t));
rc = bd->ops->write(bd->arg, hdr_ba[i], 1, gpt_hdr);
if (rc != EOK) {
rc = EIO;
goto error;
}
free(gpt_hdr);
gpt_hdr = NULL;
}
label = calloc(1, sizeof(label_t));
if (label == NULL)
return ENOMEM;
list_initialize(&label->parts);
list_initialize(&label->pri_parts);
list_initialize(&label->log_parts);
label->ops = &gpt_label_ops;
label->ltype = lt_gpt;
label->bd = *bd;
label->ablock0 = ba_min;
label->anblocks = ba_max - ba_min + 1;
label->pri_entries = num_entries;
label->block_size = bsize;
label->lt.gpt.hdr_ba[0] = hdr_ba[0];
label->lt.gpt.hdr_ba[1] = hdr_ba[1];
label->lt.gpt.ptable_ba[0] = ptba[0];
label->lt.gpt.ptable_ba[1] = ptba[1];
label->lt.gpt.esize = esize;
label->lt.gpt.pt_blocks = pt_blocks;
label->lt.gpt.pt_crc = pt_crc;
label->lt.gpt.hdr_size = sizeof(gpt_header_t);
*rlabel = label;
return EOK;
error:
free(etable);
free(gpt_hdr);
free(label);
return rc;
}
static void gpt_close(label_t *label)
{
label_part_t *part;
part = gpt_part_first(label);
while (part != NULL) {
list_remove(&part->lparts);
list_remove(&part->lpri);
free(part);
part = gpt_part_first(label);
}
free(label);
}
static errno_t gpt_destroy(label_t *label)
{
gpt_header_t *gpt_hdr = NULL;
uint8_t *etable = NULL;
label_part_t *part;
int i;
errno_t rc;
part = gpt_part_first(label);
if (part != NULL) {
rc = ENOTEMPTY;
goto error;
}
for (i = 0; i < 2; i++) {
gpt_hdr = calloc(1, label->block_size);
if (gpt_hdr == NULL) {
rc = ENOMEM;
goto error;
}
rc = label->bd.ops->write(label->bd.arg, label->lt.gpt.hdr_ba[i],
1, gpt_hdr);
if (rc != EOK) {
rc = EIO;
goto error;
}
free(gpt_hdr);
gpt_hdr = NULL;
etable = calloc(1, label->lt.gpt.pt_blocks *
label->block_size);
if (etable == NULL) {
rc = ENOMEM;
goto error;
}
rc = label->bd.ops->write(label->bd.arg,
label->lt.gpt.ptable_ba[i], label->lt.gpt.pt_blocks,
etable);
if (rc != EOK) {
rc = EIO;
goto error;
}
free(etable);
etable = 0;
}
rc = gpt_pmbr_destroy(&label->bd, label->block_size);
if (rc != EOK)
goto error;
free(label);
return EOK;
error:
return rc;
}
static bool gpt_can_create_pri(label_t *label)
{
return list_count(&label->parts) < (size_t)label->pri_entries;
}
static bool gpt_can_delete_part(label_t *label)
{
return list_count(&label->parts) > 0;
}
static bool gpt_can_modify_part(label_t *label)
{
return list_count(&label->parts) > 0;
}
static errno_t gpt_get_info(label_t *label, label_info_t *linfo)
{
memset(linfo, 0, sizeof(label_info_t));
linfo->ltype = lt_gpt;
linfo->flags = lf_ptype_uuid;
if (gpt_can_create_pri(label))
linfo->flags = linfo->flags | lf_can_create_pri;
if (gpt_can_delete_part(label))
linfo->flags = linfo->flags | lf_can_delete_part;
if (gpt_can_modify_part(label))
linfo->flags = linfo->flags | lf_can_modify_part;
linfo->ablock0 = label->ablock0;
linfo->anblocks = label->anblocks;
return EOK;
}
static label_part_t *gpt_part_first(label_t *label)
{
link_t *link;
link = list_first(&label->parts);
if (link == NULL)
return NULL;
return list_get_instance(link, label_part_t, lparts);
}
static label_part_t *gpt_part_next(label_part_t *part)
{
link_t *link;
link = list_next(&part->lparts, &part->label->parts);
if (link == NULL)
return NULL;
return list_get_instance(link, label_part_t, lparts);
}
static void gpt_part_get_info(label_part_t *part, label_part_info_t *pinfo)
{
pinfo->index = part->index;
pinfo->pkind = lpk_primary;
pinfo->block0 = part->block0;
pinfo->nblocks = part->nblocks;
}
static errno_t gpt_part_create(label_t *label, label_part_spec_t *pspec,
label_part_t **rpart)
{
label_part_t *part;
gpt_entry_t pte;
errno_t rc;
part = calloc(1, sizeof(label_part_t));
if (part == NULL) {
rc = ENOMEM;
goto error;
}
rc = gpt_check_free_idx(label, pspec->index);
if (rc != EOK) {
rc = EINVAL;
goto error;
}
rc = gpt_check_free_range(label, pspec->block0, pspec->nblocks);
if (rc != EOK) {
rc = EINVAL;
goto error;
}
if (pspec->pkind != lpk_primary) {
rc = EINVAL;
goto error;
}
if (pspec->ptype.fmt != lptf_uuid) {
rc = EINVAL;
goto error;
}
part->label = label;
part->index = pspec->index;
part->block0 = pspec->block0;
part->nblocks = pspec->nblocks;
part->ptype = pspec->ptype;
uuid_generate(&part->part_uuid);
rc = gpt_part_to_pte(part, &pte);
if (rc != EOK) {
rc = EINVAL;
goto error;
}
rc = gpt_pte_update(label, &pte, pspec->index - 1);
if (rc != EOK) {
rc = EIO;
goto error;
}
list_append(&part->lparts, &label->parts);
list_append(&part->lpri, &label->pri_parts);
*rpart = part;
return EOK;
error:
free(part);
return rc;
}
static errno_t gpt_part_destroy(label_part_t *part)
{
gpt_entry_t pte;
errno_t rc;
gpt_unused_pte(&pte);
rc = gpt_pte_update(part->label, &pte, part->index - 1);
if (rc != EOK)
return EIO;
list_remove(&part->lparts);
list_remove(&part->lpri);
free(part);
return EOK;
}
static errno_t gpt_suggest_ptype(label_t *label, label_pcnt_t pcnt,
label_ptype_t *ptype)
{
const char *ptid;
errno_t rc;
ptid = NULL;
switch (pcnt) {
case lpc_fat12_16:
case lpc_exfat:
case lpc_fat32:
ptid = GPT_MS_BASIC_DATA;
break;
case lpc_ext4:
ptid = GPT_LINUX_FS_DATA;
break;
case lpc_minix:
ptid = GPT_MINIX_FAKE;
break;
}
if (ptid == NULL)
return EINVAL;
ptype->fmt = lptf_uuid;
rc = uuid_parse(ptid, &ptype->t.uuid, NULL);
assert(rc == EOK);
return EOK;
}
static errno_t gpt_check_free_idx(label_t *label, int index)
{
label_part_t *part;
if (index < 1 || index > label->pri_entries)
return EINVAL;
part = gpt_part_first(label);
while (part != NULL) {
if (part->index == index)
return EEXIST;
part = gpt_part_next(part);
}
return EOK;
}
static bool gpt_overlap(uint64_t a0, uint64_t an, uint64_t b0, uint64_t bn)
{
return !(a0 + an <= b0 || b0 + bn <= a0);
}
static errno_t gpt_check_free_range(label_t *label, uint64_t block0,
uint64_t nblocks)
{
label_part_t *part;
if (block0 < label->ablock0)
return EINVAL;
if (block0 + nblocks > label->ablock0 + label->anblocks)
return EINVAL;
part = gpt_part_first(label);
while (part != NULL) {
if (gpt_overlap(block0, nblocks, part->block0, part->nblocks))
return EEXIST;
part = gpt_part_next(part);
}
return EOK;
}
static void gpt_unused_pte(gpt_entry_t *pte)
{
memset(pte, 0, sizeof(gpt_entry_t));
}
static errno_t gpt_part_to_pte(label_part_t *part, gpt_entry_t *pte)
{
uint64_t eblock;
eblock = part->block0 + part->nblocks - 1;
if (eblock < part->block0)
return EINVAL;
memset(pte, 0, sizeof(gpt_entry_t));
uuid_encode_le(&part->ptype.t.uuid, pte->part_type);
uuid_encode_le(&part->part_uuid, pte->part_id);
pte->start_lba = host2uint64_t_le(part->block0);
pte->end_lba = host2uint64_t_le(eblock);
return EOK;
}
static errno_t gpt_pte_to_part(label_t *label, gpt_entry_t *pte, int index)
{
label_part_t *part;
bool present;
uint64_t b0, b1;
int i;
present = false;
for (i = 0; i < 8; i++)
if (pte->part_type[i] != 0x00)
present = true;
if (!present)
return EOK;
b0 = uint64_t_le2host(pte->start_lba);
b1 = uint64_t_le2host(pte->end_lba);
if (b1 <= b0)
return EINVAL;
part = calloc(1, sizeof(label_part_t));
if (part == NULL)
return ENOMEM;
part->index = index;
part->block0 = b0;
part->nblocks = b1 - b0 + 1;
part->ptype.fmt = lptf_uuid;
uuid_decode_le(pte->part_type, &part->ptype.t.uuid);
uuid_decode_le(pte->part_id, &part->part_uuid);
part->label = label;
list_append(&part->lparts, &label->parts);
list_append(&part->lpri, &label->pri_parts);
return EOK;
}
static errno_t gpt_pte_update(label_t *label, gpt_entry_t *pte, int index)
{
size_t pos;
uint64_t ba;
uint64_t nblocks;
size_t ptbytes;
uint8_t *buf;
gpt_entry_t *e;
uint32_t crc;
int i;
errno_t rc;
pos = index * label->lt.gpt.esize;
ptbytes = label->pri_entries * label->lt.gpt.esize;
buf = calloc(1, label->block_size * label->lt.gpt.pt_blocks);
if (buf == NULL)
return ENOMEM;
for (i = 0; i < 2; i++) {
ba = label->lt.gpt.ptable_ba[i];
nblocks = label->lt.gpt.pt_blocks;
rc = label->bd.ops->read(label->bd.arg, ba, nblocks, buf);
if (rc != EOK) {
rc = EIO;
goto error;
}
crc = compute_crc32(buf, ptbytes);
if (crc != label->lt.gpt.pt_crc) {
rc = EIO;
goto error;
}
e = (gpt_entry_t *)(&buf[pos]);
*e = *pte;
rc = label->bd.ops->write(label->bd.arg, ba, nblocks, buf);
if (rc != EOK) {
rc = EIO;
goto error;
}
crc = compute_crc32(buf, ptbytes);
rc = gpt_update_pt_crc(label, crc);
if (rc != EOK) {
rc = EIO;
goto error;
}
}
label->lt.gpt.pt_crc = crc;
free(buf);
return EOK;
error:
free(buf);
return rc;
}
static errno_t gpt_update_pt_crc(label_t *label, uint32_t crc)
{
gpt_header_t *gpt_hdr;
errno_t rc;
int i;
gpt_hdr = calloc(1, label->block_size);
if (gpt_hdr == NULL) {
rc = ENOMEM;
goto exit;
}
for (i = 0; i < 2; i++) {
rc = label->bd.ops->read(label->bd.arg,
label->lt.gpt.hdr_ba[i], 1, gpt_hdr);
if (rc != EOK) {
rc = EIO;
goto exit;
}
gpt_hdr->pe_array_crc32 = host2uint32_t_le(crc);
gpt_hdr_compute_crc(gpt_hdr, label->lt.gpt.hdr_size);
rc = label->bd.ops->write(label->bd.arg,
label->lt.gpt.hdr_ba[i], 1, gpt_hdr);
if (rc != EOK) {
rc = EIO;
goto exit;
}
}
rc = EOK;
exit:
free(gpt_hdr);
return rc;
}
static void gpt_hdr_compute_crc(gpt_header_t *hdr, size_t hdr_size)
{
uint32_t crc;
hdr->header_crc32 = 0;
crc = compute_crc32((uint8_t *)hdr, hdr_size);
hdr->header_crc32 = crc;
}
static errno_t gpt_hdr_get_crc(gpt_header_t *hdr, size_t hdr_size, uint32_t *crc)
{
gpt_header_t *c;
c = calloc(1, hdr_size);
if (c == NULL)
return ENOMEM;
memcpy(c, hdr, hdr_size);
c->header_crc32 = 0;
*crc = compute_crc32((uint8_t *)c, hdr_size);
free(c);
return EOK;
}
static errno_t gpt_pmbr_create(label_bd_t *bd, size_t bsize, uint64_t nblocks)
{
mbr_br_block_t *pmbr = NULL;
uint64_t pmbr_nb;
errno_t rc;
pmbr = calloc(1, bsize);
if (pmbr == NULL) {
rc = ENOMEM;
goto error;
}
pmbr_nb = nblocks - gpt_hdr_ba;
pmbr->pte[0].ptype = mbr_pt_gpt_protect;
pmbr->pte[0].first_lba = gpt_hdr_ba;
if (pmbr_nb <= UINT32_MAX)
pmbr->pte[0].length = host2uint32_t_le((uint32_t)pmbr_nb);
else
pmbr->pte[0].length = host2uint32_t_le(UINT32_MAX);
pmbr->signature = host2uint16_t_le(mbr_br_signature);
rc = bd->ops->write(bd->arg, mbr_ba, 1, pmbr);
if (rc != EOK) {
rc = EIO;
goto error;
}
free(pmbr);
return EOK;
error:
free(pmbr);
return rc;
}
static errno_t gpt_pmbr_destroy(label_bd_t *bd, size_t bsize)
{
mbr_br_block_t *pmbr = NULL;
errno_t rc;
pmbr = calloc(1, bsize);
if (pmbr == NULL) {
rc = ENOMEM;
goto error;
}
rc = bd->ops->write(bd->arg, mbr_ba, 1, pmbr);
if (rc != EOK) {
rc = EIO;
goto error;
}
free(pmbr);
return EOK;
error:
free(pmbr);
return rc;
}
HelenOS homepage, sources at GitHub