Changeset View
Changeset View
Standalone View
Standalone View
sys/geom/part/g_part_gpt.c
Show First 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | |||||
struct g_part_gpt_entry { | struct g_part_gpt_entry { | ||||
struct g_part_entry base; | struct g_part_entry base; | ||||
struct gpt_ent ent; | struct gpt_ent ent; | ||||
}; | }; | ||||
static void g_gpt_printf_utf16(struct sbuf *, uint16_t *, size_t); | static void g_gpt_printf_utf16(struct sbuf *, uint16_t *, size_t); | ||||
static void g_gpt_utf8_to_utf16(const uint8_t *, uint16_t *, size_t); | static void g_gpt_utf8_to_utf16(const uint8_t *, uint16_t *, size_t); | ||||
static void g_gpt_set_defaults(struct g_part_table *, struct g_provider *); | static void g_gpt_set_defaults(struct g_part_table *, struct g_provider *); | ||||
static int g_gpt_set_table_start(struct g_part_table *, struct g_provider *); | |||||
static int g_part_gpt_add(struct g_part_table *, struct g_part_entry *, | static int g_part_gpt_add(struct g_part_table *, struct g_part_entry *, | ||||
struct g_part_parms *); | struct g_part_parms *); | ||||
static int g_part_gpt_bootcode(struct g_part_table *, struct g_part_parms *); | static int g_part_gpt_bootcode(struct g_part_table *, struct g_part_parms *); | ||||
static int g_part_gpt_create(struct g_part_table *, struct g_part_parms *); | static int g_part_gpt_create(struct g_part_table *, struct g_part_parms *); | ||||
static int g_part_gpt_destroy(struct g_part_table *, struct g_part_parms *); | static int g_part_gpt_destroy(struct g_part_table *, struct g_part_parms *); | ||||
static void g_part_gpt_dumpconf(struct g_part_table *, struct g_part_entry *, | static void g_part_gpt_dumpconf(struct g_part_table *, struct g_part_entry *, | ||||
struct sbuf *, const char *); | struct sbuf *, const char *); | ||||
▲ Show 20 Lines • Show All 560 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static int | static int | ||||
g_part_gpt_create(struct g_part_table *basetable, struct g_part_parms *gpp) | g_part_gpt_create(struct g_part_table *basetable, struct g_part_parms *gpp) | ||||
{ | { | ||||
struct g_provider *pp; | struct g_provider *pp; | ||||
struct g_part_gpt_table *table; | struct g_part_gpt_table *table; | ||||
size_t tblsz; | size_t tblsz; | ||||
int error; | |||||
/* Our depth should be 0 unless nesting was explicitly enabled. */ | /* Our depth should be 0 unless nesting was explicitly enabled. */ | ||||
if (!allow_nesting && basetable->gpt_depth != 0) | if (!allow_nesting && basetable->gpt_depth != 0) | ||||
return (ENXIO); | return (ENXIO); | ||||
table = (struct g_part_gpt_table *)basetable; | table = (struct g_part_gpt_table *)basetable; | ||||
pp = gpp->gpp_provider; | pp = gpp->gpp_provider; | ||||
tblsz = howmany(basetable->gpt_entries * sizeof(struct gpt_ent), | tblsz = howmany(basetable->gpt_entries * sizeof(struct gpt_ent), | ||||
pp->sectorsize); | pp->sectorsize); | ||||
if (pp->sectorsize < MBRSIZE || | if (pp->sectorsize < MBRSIZE || | ||||
pp->mediasize < (3 + 2 * tblsz + basetable->gpt_entries) * | pp->mediasize < (3 + 2 * tblsz + basetable->gpt_entries) * | ||||
pp->sectorsize) | pp->sectorsize) | ||||
return (ENOSPC); | return (ENOSPC); | ||||
/* Do a pre-check. */ | |||||
error = g_gpt_set_table_start(basetable, pp); | |||||
if (error != 0) | |||||
return (error); | |||||
gpt_create_pmbr(table, pp); | gpt_create_pmbr(table, pp); | ||||
/* Allocate space for the header */ | /* Allocate space for the header */ | ||||
table->hdr = g_malloc(sizeof(struct gpt_hdr), M_WAITOK | M_ZERO); | table->hdr = g_malloc(sizeof(struct gpt_hdr), M_WAITOK | M_ZERO); | ||||
bcopy(GPT_HDR_SIG, table->hdr->hdr_sig, sizeof(table->hdr->hdr_sig)); | bcopy(GPT_HDR_SIG, table->hdr->hdr_sig, sizeof(table->hdr->hdr_sig)); | ||||
table->hdr->hdr_revision = GPT_HDR_REVISION; | table->hdr->hdr_revision = GPT_HDR_REVISION; | ||||
table->hdr->hdr_size = offsetof(struct gpt_hdr, padding); | table->hdr->hdr_size = offsetof(struct gpt_hdr, padding); | ||||
▲ Show 20 Lines • Show All 571 Lines • ▼ Show 20 Lines | g_part_gpt_write(struct g_part_table *basetable, struct g_consumer *cp) | ||||
error = g_write_data(cp, table->lba[GPT_ELT_SECHDR] * pp->sectorsize, | error = g_write_data(cp, table->lba[GPT_ELT_SECHDR] * pp->sectorsize, | ||||
buf, pp->sectorsize); | buf, pp->sectorsize); | ||||
out: | out: | ||||
g_free(buf); | g_free(buf); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | |||||
g_gpt_set_table_start(struct g_part_table *basetable, struct g_provider *pp) | |||||
{ | |||||
struct g_part_gpt_table *table; | |||||
quad_t lba, last; | |||||
size_t tblsz; | |||||
table = (struct g_part_gpt_table *)basetable; | |||||
cem: It seems a bit odd to me to be passing a generic g_part_table between GPT-specific, static… | |||||
bzAuthorUnsubmitted Done Inline Actionswill do. bz: will do. | |||||
last = pp->mediasize / pp->sectorsize - 1; | |||||
tblsz = howmany(basetable->gpt_entries * sizeof(struct gpt_ent), | |||||
pp->sectorsize); | |||||
/* Set defaults. */ | |||||
table->lba[GPT_ELT_PRITBL] = 2; | |||||
table->lba[GPT_ELT_SECTBL] = last - tblsz; | |||||
if (basetable->gpt_tblpri_start != 0) { | |||||
lba = (basetable->gpt_tblpri_start % pp->sectorsize) ? 1 : 0; | |||||
cemUnsubmitted Not Done Inline ActionsSeems weird to accept non-sector multiples at all. cem: Seems weird to accept non-sector multiples at all. | |||||
bzAuthorUnsubmitted Done Inline ActionsCan enforce that instead of rounding up. (should round down below for tblsec anyway in that case) bz: Can enforce that instead of rounding up. (should round down below for tblsec anyway in that… | |||||
lba += basetable->gpt_tblpri_start / pp->sectorsize; | |||||
if (lba < 2 || lba > last) | |||||
return (ENOSPC); | |||||
table->lba[GPT_ELT_PRITBL] = lba; | |||||
} | |||||
if (basetable->gpt_tblsec_start != 0) { | |||||
lba = (basetable->gpt_tblsec_start % pp->sectorsize) ? 1 : 0; | |||||
lba += basetable->gpt_tblsec_start / pp->sectorsize; | |||||
if (lba < 2 + tblsz || lba > last) | |||||
return (ENOSPC); | |||||
table->lba[GPT_ELT_SECTBL] = lba; | |||||
cemUnsubmitted Not Done Inline ActionsShould we reject secondary tables before primary tables? I.e., lba <= table->lba[GPT_ELT_PRITBL] cem: Should we reject secondary tables before primary tables? I.e., `lba <= table->lba… | |||||
bzAuthorUnsubmitted Done Inline ActionsYes we should; though I should go and see if UEFI enforces that. I assume it does as first and last LBA need to be ordered too from memory. bz: Yes we should; though I should go and see if UEFI enforces that. I assume it does as first and… | |||||
} | |||||
return (0); | |||||
} | |||||
static void | static void | ||||
g_gpt_set_defaults(struct g_part_table *basetable, struct g_provider *pp) | g_gpt_set_defaults(struct g_part_table *basetable, struct g_provider *pp) | ||||
{ | { | ||||
struct g_part_entry *baseentry; | struct g_part_entry *baseentry; | ||||
struct g_part_gpt_entry *entry; | struct g_part_gpt_entry *entry; | ||||
struct g_part_gpt_table *table; | struct g_part_gpt_table *table; | ||||
quad_t start, end, min, max; | quad_t start, end, min, max; | ||||
quad_t lba, last; | quad_t lba, last; | ||||
size_t spb, tblsz; | size_t spb, tblsz; | ||||
table = (struct g_part_gpt_table *)basetable; | table = (struct g_part_gpt_table *)basetable; | ||||
last = pp->mediasize / pp->sectorsize - 1; | last = pp->mediasize / pp->sectorsize - 1; | ||||
tblsz = howmany(basetable->gpt_entries * sizeof(struct gpt_ent), | tblsz = howmany(basetable->gpt_entries * sizeof(struct gpt_ent), | ||||
pp->sectorsize); | pp->sectorsize); | ||||
table->lba[GPT_ELT_PRIHDR] = 1; | table->lba[GPT_ELT_PRIHDR] = 1; | ||||
table->lba[GPT_ELT_PRITBL] = 2; | |||||
table->lba[GPT_ELT_SECHDR] = last; | table->lba[GPT_ELT_SECHDR] = last; | ||||
table->lba[GPT_ELT_SECTBL] = last - tblsz; | g_gpt_set_table_start(basetable, pp); | ||||
table->state[GPT_ELT_PRIHDR] = GPT_STATE_OK; | table->state[GPT_ELT_PRIHDR] = GPT_STATE_OK; | ||||
table->state[GPT_ELT_PRITBL] = GPT_STATE_OK; | table->state[GPT_ELT_PRITBL] = GPT_STATE_OK; | ||||
table->state[GPT_ELT_SECHDR] = GPT_STATE_OK; | table->state[GPT_ELT_SECHDR] = GPT_STATE_OK; | ||||
table->state[GPT_ELT_SECTBL] = GPT_STATE_OK; | table->state[GPT_ELT_SECTBL] = GPT_STATE_OK; | ||||
max = start = 2 + tblsz; | max = start = table->lba[GPT_ELT_PRITBL] + tblsz; | ||||
min = end = last - tblsz - 1; | min = end = table->lba[GPT_ELT_SECTBL] - 1; | ||||
LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) { | LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) { | ||||
if (baseentry->gpe_deleted) | if (baseentry->gpe_deleted) | ||||
continue; | continue; | ||||
entry = (struct g_part_gpt_entry *)baseentry; | entry = (struct g_part_gpt_entry *)baseentry; | ||||
if (entry->ent.ent_lba_start < min) | if (entry->ent.ent_lba_start < min) | ||||
min = entry->ent.ent_lba_start; | min = entry->ent.ent_lba_start; | ||||
if (entry->ent.ent_lba_end > max) | if (entry->ent.ent_lba_end > max) | ||||
max = entry->ent.ent_lba_end; | max = entry->ent.ent_lba_end; | ||||
▲ Show 20 Lines • Show All 129 Lines • Show Last 20 Lines |
It seems a bit odd to me to be passing a generic g_part_table between GPT-specific, static functions, and then re-casting it. Might as well just pass g_part_gpt_table directly.