HelenOS sources
This source file includes following definitions.
- mbr_open
- mbr_open_ext
- mbr_create
- mbr_close
- mbr_destroy
- mbr_can_delete_part
- mbr_can_modify_part
- mbr_get_info
- mbr_part_first
- mbr_part_next
- mbr_log_part_first
- mbr_log_part_next
- mbr_log_part_prev
- mbr_pri_part_first
- mbr_pri_part_next
- mbr_part_get_info
- mbr_part_create
- mbr_part_destroy
- mbr_suggest_ptype
- mbr_overlap
- mbr_check_free_idx
- mbr_check_free_pri_range
- mbr_check_free_log_range
- mbr_unused_pte
- mbr_part_to_pte
- mbr_pte_to_part
- mbr_pte_to_log_part
- mbr_log_part_to_ptes
- mbr_pte_update
- mbr_log_part_insert
- mbr_ebr_create
- mbr_ebr_delete
- mbr_ebr_update_next
- mbr_update_log_indices
#include <byteorder.h>
#include <errno.h>
#include <mem.h>
#include <stdlib.h>
#include "std/fat.h"
#include "std/mbr.h"
#include "mbr.h"
static errno_t mbr_open(label_bd_t *, label_t **);
static errno_t mbr_open_ext(label_t *);
static errno_t mbr_create(label_bd_t *, label_t **);
static void mbr_close(label_t *);
static errno_t mbr_destroy(label_t *);
static errno_t mbr_get_info(label_t *, label_info_t *);
static label_part_t *mbr_part_first(label_t *);
static label_part_t *mbr_part_next(label_part_t *);
static void mbr_part_get_info(label_part_t *, label_part_info_t *);
static errno_t mbr_part_create(label_t *, label_part_spec_t *, label_part_t **);
static errno_t mbr_part_destroy(label_part_t *);
static errno_t mbr_suggest_ptype(label_t *, label_pcnt_t, label_ptype_t *);
static errno_t mbr_check_free_idx(label_t *, int);
static errno_t mbr_check_free_pri_range(label_t *, uint64_t, uint64_t);
static errno_t mbr_check_free_log_range(label_t *, uint64_t, uint64_t, uint64_t);
static void mbr_unused_pte(mbr_pte_t *);
static errno_t mbr_part_to_pte(label_part_t *, mbr_pte_t *);
static errno_t mbr_pte_to_part(label_t *, mbr_pte_t *, int);
static errno_t mbr_pte_to_log_part(label_t *, uint64_t, mbr_pte_t *);
static void mbr_log_part_to_ptes(label_part_t *, mbr_pte_t *, mbr_pte_t *);
static errno_t mbr_pte_update(label_t *, mbr_pte_t *, int);
static errno_t mbr_log_part_insert(label_t *, label_part_t *);
static errno_t mbr_ebr_create(label_t *, label_part_t *);
static errno_t mbr_ebr_delete(label_t *, label_part_t *);
static errno_t mbr_ebr_update_next(label_t *, label_part_t *);
static void mbr_update_log_indices(label_t *);
label_ops_t mbr_label_ops = {
.open = mbr_open,
.create = mbr_create,
.close = mbr_close,
.destroy = mbr_destroy,
.get_info = mbr_get_info,
.part_first = mbr_part_first,
.part_next = mbr_part_next,
.part_get_info = mbr_part_get_info,
.part_create = mbr_part_create,
.part_destroy = mbr_part_destroy,
.suggest_ptype = mbr_suggest_ptype
};
static errno_t mbr_open(label_bd_t *bd, label_t **rlabel)
{
label_t *label = NULL;
mbr_br_block_t *mbr = NULL;
fat_bs_t *bs;
mbr_pte_t *eptr;
uint16_t sgn;
size_t bsize;
aoff64_t nblocks;
uint32_t entry;
errno_t rc;
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;
}
if (nblocks < mbr_ablock0) {
rc = EINVAL;
goto error;
}
mbr = calloc(1, bsize);
if (mbr == NULL) {
rc = ENOMEM;
goto error;
}
bs = (fat_bs_t *)mbr;
rc = bd->ops->read(bd->arg, mbr_ba, 1, mbr);
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);
sgn = uint16_t_le2host(mbr->signature);
if (sgn != mbr_br_signature) {
rc = EIO;
goto error;
}
if (bs->type[0] == 'F' && bs->type[1] == 'A' && bs->type[2] == 'T') {
rc = EIO;
goto error;
}
if (bs->fat32.type[0] == 'F' && bs->fat32.type[1] == 'A' &&
bs->fat32.type[2] == 'T') {
rc = EIO;
goto error;
}
label->ext_part = NULL;
for (entry = 0; entry < mbr_nprimary; entry++) {
eptr = &mbr->pte[entry];
rc = mbr_pte_to_part(label, eptr, entry + 1);
if (rc != EOK)
goto error;
}
free(mbr);
mbr = NULL;
label->ops = &mbr_label_ops;
label->ltype = lt_mbr;
label->bd = *bd;
label->block_size = bsize;
label->ablock0 = mbr_ablock0;
label->anblocks = nblocks - mbr_ablock0;
label->pri_entries = mbr_nprimary;
if (label->ext_part != NULL) {
rc = mbr_open_ext(label);
if (rc != EOK)
goto error;
}
*rlabel = label;
return EOK;
error:
free(mbr);
mbr_close(label);
return rc;
}
static errno_t mbr_open_ext(label_t *label)
{
mbr_br_block_t *ebr = NULL;
mbr_pte_t *ethis;
mbr_pte_t *enext;
uint64_t ebr_b0;
uint64_t ebr_nblocks_min;
uint64_t ebr_nblocks_max;
uint64_t pebr_b0;
uint64_t pebr_nblocks;
uint64_t pb0;
uint64_t pnblocks;
uint64_t ep_b0;
errno_t rc;
ebr = calloc(1, label->block_size);
if (ebr == NULL) {
rc = ENOMEM;
goto error;
}
ep_b0 = label->ext_part->block0;
ebr_b0 = label->ext_part->block0;
ebr_nblocks_min = 1;
ebr_nblocks_max = label->ext_part->nblocks;
while (true) {
rc = label->bd.ops->read(label->bd.arg, ebr_b0, 1, ebr);
if (rc != EOK) {
rc = EIO;
goto error;
}
ethis = &ebr->pte[mbr_ebr_pte_this];
enext = &ebr->pte[mbr_ebr_pte_next];
pb0 = ebr_b0 + uint32_t_le2host(ethis->first_lba);
pnblocks = uint32_t_le2host(ethis->length);
if (ethis->ptype == mbr_pt_unused || pnblocks == 0)
break;
if (pb0 + pnblocks > ebr_b0 + ebr_nblocks_max) {
rc = EIO;
goto error;
}
rc = mbr_pte_to_log_part(label, ebr_b0, ethis);
if (rc != EOK) {
rc = EIO;
goto error;
}
pebr_b0 = ebr_b0;
pebr_nblocks = ebr_nblocks_min;
ebr_b0 = ep_b0 + uint32_t_le2host(enext->first_lba);
ebr_nblocks_min = uint32_t_le2host(enext->length);
ebr_nblocks_max = ebr_nblocks_min;
if (enext->ptype == mbr_pt_unused || ebr_nblocks_min == 0)
break;
if (ebr_b0 < pebr_b0 + pebr_nblocks) {
rc = EIO;
goto error;
}
if (ebr_b0 + ebr_nblocks_max > label->ablock0 + label->anblocks) {
rc = EIO;
goto error;
}
}
free(ebr);
return EOK;
error:
free(ebr);
return rc;
}
static errno_t mbr_create(label_bd_t *bd, label_t **rlabel)
{
label_t *label = NULL;
mbr_br_block_t *mbr = NULL;
aoff64_t nblocks;
size_t bsize;
int i;
errno_t rc;
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;
}
mbr = calloc(1, bsize);
if (mbr == NULL) {
rc = ENOMEM;
goto error;
}
label = calloc(1, sizeof(label_t));
if (label == NULL) {
rc = ENOMEM;
goto error;
}
list_initialize(&label->parts);
list_initialize(&label->pri_parts);
list_initialize(&label->log_parts);
mbr->media_id = 0;
mbr->pad0 = 0;
for (i = 0; i < mbr_nprimary; i++)
mbr_unused_pte(&mbr->pte[i]);
mbr->signature = host2uint16_t_le(mbr_br_signature);
rc = bd->ops->write(bd->arg, mbr_ba, 1, mbr);
if (rc != EOK) {
rc = EIO;
goto error;
}
free(mbr);
mbr = NULL;
label->ops = &mbr_label_ops;
label->ltype = lt_mbr;
label->block_size = bsize;
label->bd = *bd;
label->ablock0 = mbr_ablock0;
label->anblocks = nblocks - mbr_ablock0;
label->pri_entries = mbr_nprimary;
label->ext_part = NULL;
*rlabel = label;
return EOK;
error:
free(mbr);
free(label);
return rc;
}
static void mbr_close(label_t *label)
{
label_part_t *part;
if (label == NULL)
return;
part = mbr_part_first(label);
while (part != NULL) {
list_remove(&part->lparts);
if (link_used(&part->lpri))
list_remove(&part->lpri);
if (link_used(&part->llog))
list_remove(&part->llog);
free(part);
part = mbr_part_first(label);
}
free(label);
}
static errno_t mbr_destroy(label_t *label)
{
mbr_br_block_t *mbr = NULL;
label_part_t *part;
errno_t rc;
part = mbr_part_first(label);
if (part != NULL) {
rc = ENOTEMPTY;
goto error;
}
mbr = calloc(1, label->block_size);
if (mbr == NULL) {
rc = ENOMEM;
goto error;
}
rc = label->bd.ops->write(label->bd.arg, mbr_ba, 1, mbr);
if (rc != EOK) {
rc = EIO;
goto error;
}
free(mbr);
mbr = NULL;
free(label);
return EOK;
error:
free(mbr);
return rc;
}
static bool mbr_can_delete_part(label_t *label)
{
return list_count(&label->parts) > 0;
}
static bool mbr_can_modify_part(label_t *label)
{
return list_count(&label->parts) > 0;
}
static errno_t mbr_get_info(label_t *label, label_info_t *linfo)
{
memset(linfo, 0, sizeof(label_info_t));
linfo->ltype = lt_mbr;
linfo->flags = lf_ext_supp;
if (list_count(&label->pri_parts) < mbr_nprimary)
linfo->flags |= lf_can_create_pri;
if ((linfo->flags & lf_can_create_pri) != 0 && label->ext_part == NULL)
linfo->flags |= lf_can_create_ext;
if (label->ext_part != NULL)
linfo->flags |= lf_can_create_log;
if (mbr_can_delete_part(label))
linfo->flags |= lf_can_delete_part;
if (mbr_can_modify_part(label))
linfo->flags |= lf_can_modify_part;
linfo->ablock0 = label->ablock0;
linfo->anblocks = label->anblocks;
return EOK;
}
static label_part_t *mbr_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 *mbr_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 label_part_t *mbr_log_part_first(label_t *label)
{
link_t *link;
link = list_first(&label->log_parts);
if (link == NULL)
return NULL;
return list_get_instance(link, label_part_t, llog);
}
static label_part_t *mbr_log_part_next(label_part_t *part)
{
link_t *link;
link = list_next(&part->llog, &part->label->log_parts);
if (link == NULL)
return NULL;
return list_get_instance(link, label_part_t, llog);
}
static label_part_t *mbr_log_part_prev(label_part_t *part)
{
link_t *link;
link = list_prev(&part->llog, &part->label->log_parts);
if (link == NULL)
return NULL;
return list_get_instance(link, label_part_t, llog);
}
static label_part_t *mbr_pri_part_first(label_t *label)
{
link_t *link;
link = list_first(&label->pri_parts);
if (link == NULL)
return NULL;
return list_get_instance(link, label_part_t, lpri);
}
static label_part_t *mbr_pri_part_next(label_part_t *part)
{
link_t *link;
link = list_next(&part->lpri, &part->label->pri_parts);
if (link == NULL)
return NULL;
return list_get_instance(link, label_part_t, lpri);
}
static void mbr_part_get_info(label_part_t *part, label_part_info_t *pinfo)
{
pinfo->index = part->index;
pinfo->block0 = part->block0;
pinfo->nblocks = part->nblocks;
if (link_used(&part->llog))
pinfo->pkind = lpk_logical;
else if (part->ptype.t.num == mbr_pt_extended)
pinfo->pkind = lpk_extended;
else
pinfo->pkind = lpk_primary;
}
static errno_t mbr_part_create(label_t *label, label_part_spec_t *pspec,
label_part_t **rpart)
{
label_part_t *part;
label_part_t *prev;
label_part_t *next;
mbr_pte_t pte;
errno_t rc;
if (pspec->ptype.fmt != lptf_num)
return EINVAL;
part = calloc(1, sizeof(label_part_t));
if (part == NULL)
return ENOMEM;
part->label = label;
part->index = pspec->index;
part->block0 = pspec->block0;
part->nblocks = pspec->nblocks;
part->hdr_blocks = pspec->hdr_blocks;
switch (pspec->pkind) {
case lpk_primary:
part->ptype = pspec->ptype;
break;
case lpk_extended:
part->ptype.fmt = lptf_num;
part->ptype.t.num = mbr_pt_extended;
if (pspec->ptype.t.num != 0) {
rc = EINVAL;
goto error;
}
if (label->ext_part != NULL) {
rc = EEXIST;
goto error;
}
break;
case lpk_logical:
part->ptype = pspec->ptype;
if (pspec->index != 0) {
rc = EINVAL;
goto error;
}
break;
}
if (pspec->pkind != lpk_logical) {
rc = mbr_check_free_idx(label, pspec->index);
if (rc != EOK) {
rc = EINVAL;
goto error;
}
rc = mbr_check_free_pri_range(label, pspec->block0, pspec->nblocks);
if (rc != EOK) {
rc = EINVAL;
goto error;
}
if (pspec->hdr_blocks != 0) {
rc = EINVAL;
goto error;
}
rc = mbr_part_to_pte(part, &pte);
if (rc != EOK) {
rc = EINVAL;
goto error;
}
rc = mbr_pte_update(label, &pte, pspec->index - 1);
if (rc != EOK) {
rc = EIO;
goto error;
}
if (pspec->pkind == lpk_extended) {
label->ext_part = part;
rc = mbr_ebr_create(label, NULL);
if (rc != EOK) {
label->ext_part = NULL;
rc = EIO;
goto error;
}
}
list_append(&part->lparts, &label->parts);
list_append(&part->lpri, &label->pri_parts);
} else {
rc = mbr_check_free_log_range(label, pspec->hdr_blocks,
pspec->block0, pspec->nblocks);
if (rc != EOK) {
rc = EINVAL;
goto error;
}
rc = mbr_log_part_insert(label, part);
if (rc != EOK)
goto error;
rc = mbr_ebr_create(label, part);
if (rc != EOK)
goto error;
prev = mbr_log_part_prev(part);
if (prev != NULL) {
rc = mbr_ebr_update_next(label, prev);
if (rc != EOK) {
goto error;
}
} else {
next = mbr_log_part_next(part);
if (next != NULL) {
next->hdr_blocks = pspec->hdr_blocks;
rc = mbr_ebr_create(label, next);
if (rc != EOK)
goto error;
}
}
mbr_update_log_indices(label);
}
*rpart = part;
return EOK;
error:
free(part);
return rc;
}
static errno_t mbr_part_destroy(label_part_t *part)
{
mbr_pte_t pte;
label_part_t *prev;
label_part_t *next;
uint64_t ep_b0;
errno_t rc;
if (link_used(&part->lpri)) {
mbr_unused_pte(&pte);
rc = mbr_pte_update(part->label, &pte, part->index - 1);
if (rc != EOK)
return EIO;
if (part == part->label->ext_part)
part->label->ext_part = NULL;
list_remove(&part->lpri);
} else {
prev = mbr_log_part_prev(part);
if (prev != NULL) {
list_remove(&part->llog);
rc = mbr_ebr_update_next(part->label, prev);
if (rc != EOK) {
list_insert_after(&part->llog, &prev->llog);
return EIO;
}
rc = mbr_ebr_delete(part->label, part);
if (rc != EOK)
return EIO;
} else {
next = mbr_log_part_next(part);
list_remove(&part->llog);
if (next != NULL) {
ep_b0 = part->label->ext_part->block0;
next->hdr_blocks = next->block0 - ep_b0;
rc = mbr_ebr_create(part->label, next);
if (rc != EOK) {
list_prepend(&part->llog, &part->label->log_parts);
return EIO;
}
} else {
rc = mbr_ebr_delete(part->label, part);
if (rc != EOK)
return EIO;
}
}
mbr_update_log_indices(part->label);
}
list_remove(&part->lparts);
free(part);
return EOK;
}
static errno_t mbr_suggest_ptype(label_t *label, label_pcnt_t pcnt,
label_ptype_t *ptype)
{
ptype->fmt = lptf_num;
ptype->t.num = 0;
switch (pcnt) {
case lpc_exfat:
ptype->t.num = mbr_pt_ms_advanced;
break;
case lpc_ext4:
ptype->t.num = mbr_pt_linux;
break;
case lpc_fat12_16:
ptype->t.num = mbr_pt_fat16_lba;
break;
case lpc_fat32:
ptype->t.num = mbr_pt_fat32_lba;
break;
case lpc_minix:
ptype->t.num = mbr_pt_minix;
break;
}
if (ptype->t.num == 0)
return EINVAL;
return EOK;
}
static bool mbr_overlap(uint64_t a0, uint64_t an, uint64_t b0, uint64_t bn)
{
return !(a0 + an <= b0 || b0 + bn <= a0);
}
static errno_t mbr_check_free_idx(label_t *label, int index)
{
label_part_t *part;
if (index < 1 || index > label->pri_entries)
return EINVAL;
part = mbr_pri_part_first(label);
while (part != NULL) {
if (part->index == index)
return EEXIST;
part = mbr_pri_part_next(part);
}
return EOK;
}
static errno_t mbr_check_free_pri_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 = mbr_pri_part_first(label);
while (part != NULL) {
if (mbr_overlap(block0, nblocks, part->block0, part->nblocks))
return EEXIST;
part = mbr_pri_part_next(part);
}
return EOK;
}
static errno_t mbr_check_free_log_range(label_t *label, uint64_t hdr_blocks,
uint64_t block0, uint64_t nblocks)
{
label_part_t *part;
if (block0 - hdr_blocks < label->ext_part->block0)
return EINVAL;
if (block0 + nblocks > label->ext_part->block0 + label->ext_part->nblocks)
return EINVAL;
part = mbr_log_part_first(label);
while (part != NULL) {
if (mbr_overlap(block0 - hdr_blocks, nblocks + hdr_blocks,
part->block0 - part->hdr_blocks, part->nblocks + part->hdr_blocks))
return EEXIST;
part = mbr_log_part_next(part);
}
return EOK;
}
static void mbr_unused_pte(mbr_pte_t *pte)
{
memset(pte, 0, sizeof(mbr_pte_t));
}
static errno_t mbr_part_to_pte(label_part_t *part, mbr_pte_t *pte)
{
if ((part->block0 >> 32) != 0)
return EINVAL;
if ((part->nblocks >> 32) != 0)
return EINVAL;
if ((part->ptype.t.num >> 8) != 0)
return EINVAL;
memset(pte, 0, sizeof(mbr_pte_t));
pte->ptype = part->ptype.t.num;
pte->first_lba = host2uint32_t_le(part->block0);
pte->length = host2uint32_t_le(part->nblocks);
return EOK;
}
static errno_t mbr_pte_to_part(label_t *label, mbr_pte_t *pte, int index)
{
label_part_t *part;
uint32_t block0;
uint32_t nblocks;
block0 = uint32_t_le2host(pte->first_lba);
nblocks = uint32_t_le2host(pte->length);
if (pte->ptype == mbr_pt_unused || nblocks == 0)
return EOK;
part = calloc(1, sizeof(label_part_t));
if (part == NULL)
return ENOMEM;
part->ptype.fmt = lptf_num;
part->ptype.t.num = pte->ptype;
part->index = index;
part->block0 = block0;
part->nblocks = nblocks;
part->label = label;
list_append(&part->lparts, &label->parts);
list_append(&part->lpri, &label->pri_parts);
if (pte->ptype == mbr_pt_extended)
label->ext_part = part;
return EOK;
}
static errno_t mbr_pte_to_log_part(label_t *label, uint64_t ebr_b0,
mbr_pte_t *pte)
{
label_part_t *part;
uint32_t block0;
uint32_t nblocks;
size_t nlparts;
block0 = ebr_b0 + uint32_t_le2host(pte->first_lba);
nblocks = uint32_t_le2host(pte->length);
if (pte->ptype == mbr_pt_unused || nblocks == 0)
return EOK;
part = calloc(1, sizeof(label_part_t));
if (part == NULL)
return ENOMEM;
nlparts = list_count(&label->log_parts);
part->ptype.fmt = lptf_num;
part->ptype.t.num = pte->ptype;
part->index = mbr_nprimary + 1 + nlparts;
part->block0 = block0;
part->nblocks = nblocks;
part->hdr_blocks = block0 - ebr_b0;
part->label = label;
list_append(&part->lparts, &label->parts);
list_append(&part->llog, &label->log_parts);
return EOK;
}
static void mbr_log_part_to_ptes(label_part_t *part, mbr_pte_t *pthis,
mbr_pte_t *pnext)
{
label_part_t *next;
uint64_t ep_b0;
uint64_t totsize;
ep_b0 = part->label->ext_part->block0;
assert(link_used(&part->llog));
assert(part->block0 >= ep_b0);
assert(part->hdr_blocks <= part->block0 - ep_b0);
if (pthis != NULL) {
memset(pthis, 0, sizeof(mbr_pte_t));
pthis->ptype = part->ptype.t.num;
pthis->first_lba = host2uint32_t_le(part->hdr_blocks);
pthis->length = host2uint32_t_le(part->nblocks);
}
if (pnext != NULL) {
next = mbr_log_part_next(part);
memset(pnext, 0, sizeof(mbr_pte_t));
if (next != NULL) {
totsize = next->hdr_blocks + next->nblocks;
pnext->ptype = mbr_pt_extended;
pnext->first_lba = host2uint32_t_le(next->block0 -
next->hdr_blocks - ep_b0);
pnext->length = host2uint32_t_le(totsize);
}
}
}
static errno_t mbr_pte_update(label_t *label, mbr_pte_t *pte, int index)
{
mbr_br_block_t *br;
errno_t rc;
br = calloc(1, label->block_size);
if (br == NULL)
return ENOMEM;
rc = label->bd.ops->read(label->bd.arg, mbr_ba, 1, br);
if (rc != EOK) {
rc = EIO;
goto error;
}
br->pte[index] = *pte;
rc = label->bd.ops->write(label->bd.arg, mbr_ba, 1, br);
if (rc != EOK) {
rc = EIO;
goto error;
}
free(br);
return EOK;
error:
free(br);
return rc;
}
static errno_t mbr_log_part_insert(label_t *label, label_part_t *part)
{
label_part_t *cur;
cur = mbr_log_part_first(label);
while (cur != NULL) {
if (cur->block0 + cur->nblocks > part->block0)
break;
cur = mbr_log_part_next(part);
}
if (cur != NULL)
list_insert_before(&part->llog, &cur->llog);
else
list_append(&part->llog, &label->log_parts);
return EOK;
}
static errno_t mbr_ebr_create(label_t *label, label_part_t *part)
{
mbr_br_block_t *br;
uint64_t ba;
errno_t rc;
br = calloc(1, label->block_size);
if (br == NULL)
return ENOMEM;
if (part != NULL) {
ba = part->block0 - part->hdr_blocks;
mbr_log_part_to_ptes(part, &br->pte[mbr_ebr_pte_this],
&br->pte[mbr_ebr_pte_next]);
} else {
ba = label->ext_part->block0;
}
br->signature = host2uint16_t_le(mbr_br_signature);
rc = label->bd.ops->write(label->bd.arg, ba, 1, br);
if (rc != EOK) {
rc = EIO;
goto error;
}
free(br);
return EOK;
error:
free(br);
return rc;
}
static errno_t mbr_ebr_delete(label_t *label, label_part_t *part)
{
mbr_br_block_t *br;
uint64_t ba;
errno_t rc;
br = calloc(1, label->block_size);
if (br == NULL)
return ENOMEM;
ba = part->block0 - part->hdr_blocks;
rc = label->bd.ops->write(label->bd.arg, ba, 1, br);
if (rc != EOK) {
rc = EIO;
goto error;
}
free(br);
return EOK;
error:
free(br);
return rc;
}
static errno_t mbr_ebr_update_next(label_t *label, label_part_t *part)
{
mbr_br_block_t *br;
uint64_t ba;
uint16_t sgn;
errno_t rc;
ba = part->block0 - part->hdr_blocks;
br = calloc(1, label->block_size);
if (br == NULL)
return ENOMEM;
rc = label->bd.ops->read(label->bd.arg, ba, 1, br);
if (rc != EOK) {
rc = EIO;
goto error;
}
sgn = uint16_t_le2host(br->signature);
if (sgn != mbr_br_signature) {
rc = EIO;
goto error;
}
mbr_log_part_to_ptes(part, NULL, &br->pte[mbr_ebr_pte_next]);
rc = label->bd.ops->write(label->bd.arg, ba, 1, br);
if (rc != EOK) {
rc = EIO;
goto error;
}
free(br);
return EOK;
error:
free(br);
return rc;
}
static void mbr_update_log_indices(label_t *label)
{
label_part_t *part;
int idx;
idx = mbr_nprimary + 1;
part = mbr_log_part_first(label);
while (part != NULL) {
part->index = idx++;
part = mbr_log_part_next(part);
}
}
HelenOS homepage, sources at GitHub