summaryrefslogtreecommitdiffstats
path: root/sys/geom/part/g_part_gpt.c
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2008-04-13 19:54:54 +0000
committermarcel <marcel@FreeBSD.org>2008-04-13 19:54:54 +0000
commitecdc3b6d8cb8fe43a5a096731e33c747f18b2c1c (patch)
tree25a3cecb6daae88c1853a0d3087628903e6d9f72 /sys/geom/part/g_part_gpt.c
parenta3d2be176f396ea6c3fc51b7ca25b82d6680924a (diff)
downloadFreeBSD-src-ecdc3b6d8cb8fe43a5a096731e33c747f18b2c1c.zip
FreeBSD-src-ecdc3b6d8cb8fe43a5a096731e33c747f18b2c1c.tar.gz
Add the bootcode verb for installing boot code. Boot code
is supported for the MBR, GPT and PC98 schemes, where GPT installs boot code into the PMBR.
Diffstat (limited to 'sys/geom/part/g_part_gpt.c')
-rw-r--r--sys/geom/part/g_part_gpt.c66
1 files changed, 45 insertions, 21 deletions
diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c
index c6cd356..cc9cdfc 100644
--- a/sys/geom/part/g_part_gpt.c
+++ b/sys/geom/part/g_part_gpt.c
@@ -52,6 +52,8 @@ CTASSERT(sizeof(struct gpt_ent) == 128);
#define EQUUID(a,b) (memcmp(a, b, sizeof(struct uuid)) == 0)
+#define MBRSIZE 512
+
enum gpt_elt {
GPT_ELT_PRIHDR,
GPT_ELT_PRITBL,
@@ -70,6 +72,7 @@ enum gpt_state {
struct g_part_gpt_table {
struct g_part_table base;
+ u_char mbr[MBRSIZE];
struct gpt_hdr hdr;
quad_t lba[GPT_ELT_COUNT];
enum gpt_state state[GPT_ELT_COUNT];
@@ -82,6 +85,7 @@ struct g_part_gpt_entry {
static int g_part_gpt_add(struct g_part_table *, struct g_part_entry *,
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_destroy(struct g_part_table *, struct g_part_parms *);
static int g_part_gpt_dumpto(struct g_part_table *, struct g_part_entry *);
@@ -97,6 +101,7 @@ static int g_part_gpt_write(struct g_part_table *, struct g_consumer *);
static kobj_method_t g_part_gpt_methods[] = {
KOBJMETHOD(g_part_add, g_part_gpt_add),
+ KOBJMETHOD(g_part_bootcode, g_part_gpt_bootcode),
KOBJMETHOD(g_part_create, g_part_gpt_create),
KOBJMETHOD(g_part_destroy, g_part_gpt_destroy),
KOBJMETHOD(g_part_dumpto, g_part_gpt_dumpto),
@@ -116,6 +121,7 @@ static struct g_part_scheme g_part_gpt_scheme = {
.gps_entrysz = sizeof(struct g_part_gpt_entry),
.gps_minent = 128,
.gps_maxent = INT_MAX,
+ .gps_bootcodesz = MBRSIZE,
};
G_PART_SCHEME_DECLARE(g_part_gpt);
@@ -352,6 +358,16 @@ g_part_gpt_add(struct g_part_table *basetable, struct g_part_entry *baseentry,
}
static int
+g_part_gpt_bootcode(struct g_part_table *basetable, struct g_part_parms *gpp)
+{
+ struct g_part_gpt_table *table;
+
+ table = (struct g_part_gpt_table *)basetable;
+ bcopy(gpp->gpp_codeptr, table->mbr, DOSPARTOFF);
+ return (0);
+}
+
+static int
g_part_gpt_create(struct g_part_table *basetable, struct g_part_parms *gpp)
{
struct g_provider *pp;
@@ -363,13 +379,24 @@ g_part_gpt_create(struct g_part_table *basetable, struct g_part_parms *gpp)
pp = gpp->gpp_provider;
tblsz = (basetable->gpt_entries * sizeof(struct gpt_ent) +
pp->sectorsize - 1) / pp->sectorsize;
- if (pp->sectorsize < 512 ||
+ if (pp->sectorsize < MBRSIZE ||
pp->mediasize < (3 + 2 * tblsz + basetable->gpt_entries) *
pp->sectorsize)
return (ENOSPC);
last = (pp->mediasize / pp->sectorsize) - 1;
+ le16enc(table->mbr + DOSMAGICOFFSET, DOSMAGIC);
+ table->mbr[DOSPARTOFF + 1] = 0xff; /* shd */
+ table->mbr[DOSPARTOFF + 2] = 0xff; /* ssect */
+ table->mbr[DOSPARTOFF + 3] = 0xff; /* scyl */
+ table->mbr[DOSPARTOFF + 4] = 0xee; /* typ */
+ table->mbr[DOSPARTOFF + 5] = 0xff; /* ehd */
+ table->mbr[DOSPARTOFF + 6] = 0xff; /* esect */
+ table->mbr[DOSPARTOFF + 7] = 0xff; /* ecyl */
+ le32enc(table->mbr + DOSPARTOFF + 8, 1); /* start */
+ le32enc(table->mbr + DOSPARTOFF + 12, MIN(last, 0xffffffffLL));
+
table->lba[GPT_ELT_PRIHDR] = 1;
table->lba[GPT_ELT_PRITBL] = 2;
table->lba[GPT_ELT_SECHDR] = last;
@@ -469,7 +496,7 @@ g_part_gpt_probe(struct g_part_table *table, struct g_consumer *cp)
* It's better to catch this pathological case early than behaving
* pathologically later on...
*/
- if (pp->sectorsize < 512 || pp->mediasize < 6 * pp->sectorsize)
+ if (pp->sectorsize < MBRSIZE || pp->mediasize < 6 * pp->sectorsize)
return (ENOSPC);
/* Check that there's a MBR. */
@@ -508,11 +535,19 @@ g_part_gpt_read(struct g_part_table *basetable, struct g_consumer *cp)
struct g_provider *pp;
struct g_part_gpt_table *table;
struct g_part_gpt_entry *entry;
- int index;
+ u_char *buf;
+ int error, index;
table = (struct g_part_gpt_table *)basetable;
pp = cp->provider;
+ /* Read the PMBR */
+ buf = g_read_data(cp, 0, pp->sectorsize, &error);
+ if (buf == NULL)
+ return (error);
+ bcopy(buf, table->mbr, MBRSIZE);
+ g_free(buf);
+
/* Read the primary header and table. */
gpt_read_hdr(table, cp, GPT_ELT_PRIHDR, &prihdr);
if (table->state[GPT_ELT_PRIHDR] == GPT_STATE_OK) {
@@ -640,24 +675,13 @@ g_part_gpt_write(struct g_part_table *basetable, struct g_consumer *cp)
tlbsz = (table->hdr.hdr_entries * table->hdr.hdr_entsz +
pp->sectorsize - 1) / pp->sectorsize;
- if (basetable->gpt_created) {
- buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO);
- le16enc(buf + DOSMAGICOFFSET, DOSMAGIC);
- buf[DOSPARTOFF + 1] = 0xff; /* shd */
- buf[DOSPARTOFF + 2] = 0xff; /* ssect */
- buf[DOSPARTOFF + 3] = 0xff; /* scyl */
- buf[DOSPARTOFF + 4] = 0xee; /* typ */
- buf[DOSPARTOFF + 5] = 0xff; /* ehd */
- buf[DOSPARTOFF + 6] = 0xff; /* esect */
- buf[DOSPARTOFF + 7] = 0xff; /* ecyl */
- le32enc(buf + DOSPARTOFF + 8, 1); /* start */
- le32enc(buf + DOSPARTOFF + 12,
- MIN(pp->mediasize / pp->sectorsize - 1, 0xffffffffLL));
- error = g_write_data(cp, 0, buf, pp->sectorsize);
- g_free(buf);
- if (error)
- return (error);
- }
+ /* Write the PMBR */
+ buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO);
+ bcopy(table->mbr, buf, MBRSIZE);
+ error = g_write_data(cp, 0, buf, pp->sectorsize);
+ g_free(buf);
+ if (error)
+ return (error);
/* Allocate space for the header and entries. */
buf = g_malloc((tlbsz + 1) * pp->sectorsize, M_WAITOK | M_ZERO);
OpenPOWER on IntegriCloud