15d68db5bSMarcel Moolenaar /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
33728855aSPedro F. Giffuni *
45d68db5bSMarcel Moolenaar * Copyright (c) 2007-2009 Marcel Moolenaar
55d68db5bSMarcel Moolenaar * All rights reserved.
65d68db5bSMarcel Moolenaar *
75d68db5bSMarcel Moolenaar * Redistribution and use in source and binary forms, with or without
85d68db5bSMarcel Moolenaar * modification, are permitted provided that the following conditions
95d68db5bSMarcel Moolenaar * are met:
105d68db5bSMarcel Moolenaar *
115d68db5bSMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright
125d68db5bSMarcel Moolenaar * notice, this list of conditions and the following disclaimer.
135d68db5bSMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright
145d68db5bSMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the
155d68db5bSMarcel Moolenaar * documentation and/or other materials provided with the distribution.
165d68db5bSMarcel Moolenaar *
175d68db5bSMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
185d68db5bSMarcel Moolenaar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
195d68db5bSMarcel Moolenaar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
205d68db5bSMarcel Moolenaar * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
215d68db5bSMarcel Moolenaar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
225d68db5bSMarcel Moolenaar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235d68db5bSMarcel Moolenaar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245d68db5bSMarcel Moolenaar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255d68db5bSMarcel Moolenaar * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
265d68db5bSMarcel Moolenaar * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275d68db5bSMarcel Moolenaar */
285d68db5bSMarcel Moolenaar
296ad9a99fSMarcel Moolenaar #include "opt_geom.h"
306ad9a99fSMarcel Moolenaar
315d68db5bSMarcel Moolenaar #include <sys/param.h>
325d68db5bSMarcel Moolenaar #include <sys/bio.h>
335d68db5bSMarcel Moolenaar #include <sys/diskmbr.h>
345d68db5bSMarcel Moolenaar #include <sys/endian.h>
355d68db5bSMarcel Moolenaar #include <sys/kernel.h>
365d68db5bSMarcel Moolenaar #include <sys/kobj.h>
375d68db5bSMarcel Moolenaar #include <sys/limits.h>
385d68db5bSMarcel Moolenaar #include <sys/lock.h>
395d68db5bSMarcel Moolenaar #include <sys/malloc.h>
405d68db5bSMarcel Moolenaar #include <sys/mutex.h>
415d68db5bSMarcel Moolenaar #include <sys/queue.h>
425d68db5bSMarcel Moolenaar #include <sys/sbuf.h>
435d68db5bSMarcel Moolenaar #include <sys/systm.h>
44cb08c2ccSAlexander Leidinger #include <sys/sysctl.h>
455d68db5bSMarcel Moolenaar #include <geom/geom.h>
465d68db5bSMarcel Moolenaar #include <geom/part/g_part.h>
475d68db5bSMarcel Moolenaar
485d68db5bSMarcel Moolenaar #include "g_part_if.h"
495d68db5bSMarcel Moolenaar
50cb08c2ccSAlexander Leidinger FEATURE(geom_part_ebr,
51cb08c2ccSAlexander Leidinger "GEOM partitioning class for extended boot records support");
52cb08c2ccSAlexander Leidinger FEATURE(geom_part_ebr_compat,
53cb08c2ccSAlexander Leidinger "GEOM EBR partitioning class: backward-compatible partition names");
54cb08c2ccSAlexander Leidinger
5564612d4eSConrad Meyer SYSCTL_DECL(_kern_geom_part);
5664612d4eSConrad Meyer static SYSCTL_NODE(_kern_geom_part, OID_AUTO, ebr, CTLFLAG_RW | CTLFLAG_MPSAFE,
5764612d4eSConrad Meyer 0, "GEOM_PART_EBR Extended Boot Record");
5864612d4eSConrad Meyer
5964612d4eSConrad Meyer #define EBRNAMFMT "+%08u"
605d68db5bSMarcel Moolenaar #define EBRSIZE 512
615d68db5bSMarcel Moolenaar
625d68db5bSMarcel Moolenaar struct g_part_ebr_table {
635d68db5bSMarcel Moolenaar struct g_part_table base;
6464612d4eSConrad Meyer u_char lba0_ebr[EBRSIZE];
655d68db5bSMarcel Moolenaar };
665d68db5bSMarcel Moolenaar
675d68db5bSMarcel Moolenaar struct g_part_ebr_entry {
685d68db5bSMarcel Moolenaar struct g_part_entry base;
695d68db5bSMarcel Moolenaar struct dos_partition ent;
7064612d4eSConrad Meyer u_char ebr[EBRSIZE];
7164612d4eSConrad Meyer u_int ebr_compat_idx;
725d68db5bSMarcel Moolenaar };
735d68db5bSMarcel Moolenaar
745d68db5bSMarcel Moolenaar static int g_part_ebr_add(struct g_part_table *, struct g_part_entry *,
755d68db5bSMarcel Moolenaar struct g_part_parms *);
7664612d4eSConrad Meyer static void g_part_ebr_add_alias(struct g_part_table *, struct g_provider *,
7764612d4eSConrad Meyer struct g_part_entry *, const char *);
785d68db5bSMarcel Moolenaar static int g_part_ebr_create(struct g_part_table *, struct g_part_parms *);
795d68db5bSMarcel Moolenaar static int g_part_ebr_destroy(struct g_part_table *, struct g_part_parms *);
805d68db5bSMarcel Moolenaar static void g_part_ebr_dumpconf(struct g_part_table *, struct g_part_entry *,
815d68db5bSMarcel Moolenaar struct sbuf *, const char *);
825d68db5bSMarcel Moolenaar static int g_part_ebr_dumpto(struct g_part_table *, struct g_part_entry *);
835d68db5bSMarcel Moolenaar static int g_part_ebr_modify(struct g_part_table *, struct g_part_entry *,
845d68db5bSMarcel Moolenaar struct g_part_parms *);
855d68db5bSMarcel Moolenaar static const char *g_part_ebr_name(struct g_part_table *, struct g_part_entry *,
865d68db5bSMarcel Moolenaar char *, size_t);
8764612d4eSConrad Meyer static struct g_provider *g_part_ebr_new_provider(struct g_part_table *,
8864612d4eSConrad Meyer struct g_geom *, struct g_part_entry *, const char *);
89e24c8a3fSMarcel Moolenaar static int g_part_ebr_precheck(struct g_part_table *, enum g_part_ctl,
90e24c8a3fSMarcel Moolenaar struct g_part_parms *);
915d68db5bSMarcel Moolenaar static int g_part_ebr_probe(struct g_part_table *, struct g_consumer *);
925d68db5bSMarcel Moolenaar static int g_part_ebr_read(struct g_part_table *, struct g_consumer *);
935d68db5bSMarcel Moolenaar static int g_part_ebr_setunset(struct g_part_table *, struct g_part_entry *,
945d68db5bSMarcel Moolenaar const char *, unsigned int);
955d68db5bSMarcel Moolenaar static const char *g_part_ebr_type(struct g_part_table *, struct g_part_entry *,
965d68db5bSMarcel Moolenaar char *, size_t);
975d68db5bSMarcel Moolenaar static int g_part_ebr_write(struct g_part_table *, struct g_consumer *);
98884c8e4fSAndrey V. Elsukov static int g_part_ebr_resize(struct g_part_table *, struct g_part_entry *,
99884c8e4fSAndrey V. Elsukov struct g_part_parms *);
1005d68db5bSMarcel Moolenaar
1015d68db5bSMarcel Moolenaar static kobj_method_t g_part_ebr_methods[] = {
1025d68db5bSMarcel Moolenaar KOBJMETHOD(g_part_add, g_part_ebr_add),
10364612d4eSConrad Meyer KOBJMETHOD(g_part_add_alias, g_part_ebr_add_alias),
1045d68db5bSMarcel Moolenaar KOBJMETHOD(g_part_create, g_part_ebr_create),
1055d68db5bSMarcel Moolenaar KOBJMETHOD(g_part_destroy, g_part_ebr_destroy),
1065d68db5bSMarcel Moolenaar KOBJMETHOD(g_part_dumpconf, g_part_ebr_dumpconf),
1075d68db5bSMarcel Moolenaar KOBJMETHOD(g_part_dumpto, g_part_ebr_dumpto),
1085d68db5bSMarcel Moolenaar KOBJMETHOD(g_part_modify, g_part_ebr_modify),
1095d68db5bSMarcel Moolenaar KOBJMETHOD(g_part_name, g_part_ebr_name),
11064612d4eSConrad Meyer KOBJMETHOD(g_part_new_provider, g_part_ebr_new_provider),
111e24c8a3fSMarcel Moolenaar KOBJMETHOD(g_part_precheck, g_part_ebr_precheck),
1125d68db5bSMarcel Moolenaar KOBJMETHOD(g_part_probe, g_part_ebr_probe),
1135d68db5bSMarcel Moolenaar KOBJMETHOD(g_part_read, g_part_ebr_read),
114884c8e4fSAndrey V. Elsukov KOBJMETHOD(g_part_resize, g_part_ebr_resize),
1155d68db5bSMarcel Moolenaar KOBJMETHOD(g_part_setunset, g_part_ebr_setunset),
1165d68db5bSMarcel Moolenaar KOBJMETHOD(g_part_type, g_part_ebr_type),
1175d68db5bSMarcel Moolenaar KOBJMETHOD(g_part_write, g_part_ebr_write),
1185d68db5bSMarcel Moolenaar { 0, 0 }
1195d68db5bSMarcel Moolenaar };
1205d68db5bSMarcel Moolenaar
1215d68db5bSMarcel Moolenaar static struct g_part_scheme g_part_ebr_scheme = {
1225d68db5bSMarcel Moolenaar "EBR",
1235d68db5bSMarcel Moolenaar g_part_ebr_methods,
1245d68db5bSMarcel Moolenaar sizeof(struct g_part_ebr_table),
1255d68db5bSMarcel Moolenaar .gps_entrysz = sizeof(struct g_part_ebr_entry),
1265d68db5bSMarcel Moolenaar .gps_minent = 1,
127*09c999b1SWarner Losh .gps_defent = 1,
1285d68db5bSMarcel Moolenaar .gps_maxent = INT_MAX,
1295d68db5bSMarcel Moolenaar };
1305d68db5bSMarcel Moolenaar G_PART_SCHEME_DECLARE(g_part_ebr);
13174d6c131SKyle Evans MODULE_VERSION(geom_part_ebr, 0);
1325d68db5bSMarcel Moolenaar
13388007f61SAndrey V. Elsukov static struct g_part_ebr_alias {
13488007f61SAndrey V. Elsukov u_char typ;
13588007f61SAndrey V. Elsukov int alias;
13688007f61SAndrey V. Elsukov } ebr_alias_match[] = {
13788007f61SAndrey V. Elsukov { DOSPTYP_386BSD, G_PART_ALIAS_FREEBSD },
13876db6c87SEd Maste { DOSPTYP_EFI, G_PART_ALIAS_EFI },
13988007f61SAndrey V. Elsukov { DOSPTYP_FAT32, G_PART_ALIAS_MS_FAT32 },
140b525a10aSEd Maste { DOSPTYP_FAT32LBA, G_PART_ALIAS_MS_FAT32LBA },
14188007f61SAndrey V. Elsukov { DOSPTYP_LINLVM, G_PART_ALIAS_LINUX_LVM },
14288007f61SAndrey V. Elsukov { DOSPTYP_LINRAID, G_PART_ALIAS_LINUX_RAID },
143a0a8412bSEd Maste { DOSPTYP_LINSWP, G_PART_ALIAS_LINUX_SWAP },
144a0a8412bSEd Maste { DOSPTYP_LINUX, G_PART_ALIAS_LINUX_DATA },
145a0a8412bSEd Maste { DOSPTYP_NTFS, G_PART_ALIAS_MS_NTFS },
14688007f61SAndrey V. Elsukov };
14788007f61SAndrey V. Elsukov
148e24c8a3fSMarcel Moolenaar static void ebr_set_chs(struct g_part_table *, uint32_t, u_char *, u_char *,
149e24c8a3fSMarcel Moolenaar u_char *);
150e24c8a3fSMarcel Moolenaar
1515d68db5bSMarcel Moolenaar static void
ebr_entry_decode(const char * p,struct dos_partition * ent)1525d68db5bSMarcel Moolenaar ebr_entry_decode(const char *p, struct dos_partition *ent)
1535d68db5bSMarcel Moolenaar {
1545d68db5bSMarcel Moolenaar ent->dp_flag = p[0];
1555d68db5bSMarcel Moolenaar ent->dp_shd = p[1];
1565d68db5bSMarcel Moolenaar ent->dp_ssect = p[2];
1575d68db5bSMarcel Moolenaar ent->dp_scyl = p[3];
1585d68db5bSMarcel Moolenaar ent->dp_typ = p[4];
1595d68db5bSMarcel Moolenaar ent->dp_ehd = p[5];
1605d68db5bSMarcel Moolenaar ent->dp_esect = p[6];
1615d68db5bSMarcel Moolenaar ent->dp_ecyl = p[7];
1625d68db5bSMarcel Moolenaar ent->dp_start = le32dec(p + 8);
1635d68db5bSMarcel Moolenaar ent->dp_size = le32dec(p + 12);
1645d68db5bSMarcel Moolenaar }
1655d68db5bSMarcel Moolenaar
166e24c8a3fSMarcel Moolenaar static void
ebr_entry_link(struct g_part_table * table,uint32_t start,uint32_t end,u_char * buf)167e24c8a3fSMarcel Moolenaar ebr_entry_link(struct g_part_table *table, uint32_t start, uint32_t end,
168e24c8a3fSMarcel Moolenaar u_char *buf)
169e24c8a3fSMarcel Moolenaar {
170e24c8a3fSMarcel Moolenaar
171e24c8a3fSMarcel Moolenaar buf[0] = 0 /* dp_flag */;
172e24c8a3fSMarcel Moolenaar ebr_set_chs(table, start, &buf[3] /* dp_scyl */, &buf[1] /* dp_shd */,
173e24c8a3fSMarcel Moolenaar &buf[2] /* dp_ssect */);
17464612d4eSConrad Meyer buf[4] = DOSPTYP_EXT /* dp_typ */;
175e24c8a3fSMarcel Moolenaar ebr_set_chs(table, end, &buf[7] /* dp_ecyl */, &buf[5] /* dp_ehd */,
176e24c8a3fSMarcel Moolenaar &buf[6] /* dp_esect */);
177e24c8a3fSMarcel Moolenaar le32enc(buf + 8, start);
178e24c8a3fSMarcel Moolenaar le32enc(buf + 12, end - start + 1);
179e24c8a3fSMarcel Moolenaar }
180e24c8a3fSMarcel Moolenaar
181e24c8a3fSMarcel Moolenaar static int
ebr_parse_type(const char * type,u_char * dp_typ)182e24c8a3fSMarcel Moolenaar ebr_parse_type(const char *type, u_char *dp_typ)
183e24c8a3fSMarcel Moolenaar {
184e24c8a3fSMarcel Moolenaar const char *alias;
185e24c8a3fSMarcel Moolenaar char *endp;
186e24c8a3fSMarcel Moolenaar long lt;
18788007f61SAndrey V. Elsukov int i;
188e24c8a3fSMarcel Moolenaar
189e24c8a3fSMarcel Moolenaar if (type[0] == '!') {
190e24c8a3fSMarcel Moolenaar lt = strtol(type + 1, &endp, 0);
191e24c8a3fSMarcel Moolenaar if (type[1] == '\0' || *endp != '\0' || lt <= 0 || lt >= 256)
192e24c8a3fSMarcel Moolenaar return (EINVAL);
193e24c8a3fSMarcel Moolenaar *dp_typ = (u_char)lt;
194e24c8a3fSMarcel Moolenaar return (0);
195e24c8a3fSMarcel Moolenaar }
19663b6b7a7SPedro F. Giffuni for (i = 0; i < nitems(ebr_alias_match); i++) {
19788007f61SAndrey V. Elsukov alias = g_part_alias_name(ebr_alias_match[i].alias);
19888007f61SAndrey V. Elsukov if (strcasecmp(type, alias) == 0) {
19988007f61SAndrey V. Elsukov *dp_typ = ebr_alias_match[i].typ;
200e24c8a3fSMarcel Moolenaar return (0);
201e24c8a3fSMarcel Moolenaar }
20288007f61SAndrey V. Elsukov }
203e24c8a3fSMarcel Moolenaar return (EINVAL);
204e24c8a3fSMarcel Moolenaar }
205e24c8a3fSMarcel Moolenaar
206e24c8a3fSMarcel Moolenaar static void
ebr_set_chs(struct g_part_table * table,uint32_t lba,u_char * cylp,u_char * hdp,u_char * secp)207e24c8a3fSMarcel Moolenaar ebr_set_chs(struct g_part_table *table, uint32_t lba, u_char *cylp, u_char *hdp,
208e24c8a3fSMarcel Moolenaar u_char *secp)
209e24c8a3fSMarcel Moolenaar {
210e24c8a3fSMarcel Moolenaar uint32_t cyl, hd, sec;
211e24c8a3fSMarcel Moolenaar
212e24c8a3fSMarcel Moolenaar sec = lba % table->gpt_sectors + 1;
213e24c8a3fSMarcel Moolenaar lba /= table->gpt_sectors;
214e24c8a3fSMarcel Moolenaar hd = lba % table->gpt_heads;
215e24c8a3fSMarcel Moolenaar lba /= table->gpt_heads;
216e24c8a3fSMarcel Moolenaar cyl = lba;
217e24c8a3fSMarcel Moolenaar if (cyl > 1023)
218e24c8a3fSMarcel Moolenaar sec = hd = cyl = ~0;
219e24c8a3fSMarcel Moolenaar
220e24c8a3fSMarcel Moolenaar *cylp = cyl & 0xff;
221e24c8a3fSMarcel Moolenaar *hdp = hd & 0xff;
222e24c8a3fSMarcel Moolenaar *secp = (sec & 0x3f) | ((cyl >> 2) & 0xc0);
223e24c8a3fSMarcel Moolenaar }
224e24c8a3fSMarcel Moolenaar
2255d68db5bSMarcel Moolenaar static int
ebr_align(struct g_part_table * basetable,uint32_t * start,uint32_t * size)226bc1e8f56SAndrey V. Elsukov ebr_align(struct g_part_table *basetable, uint32_t *start, uint32_t *size)
227bc1e8f56SAndrey V. Elsukov {
228bc1e8f56SAndrey V. Elsukov uint32_t sectors;
229bc1e8f56SAndrey V. Elsukov
230bc1e8f56SAndrey V. Elsukov sectors = basetable->gpt_sectors;
231bc1e8f56SAndrey V. Elsukov if (*size < 2 * sectors)
232bc1e8f56SAndrey V. Elsukov return (EINVAL);
233bc1e8f56SAndrey V. Elsukov if (*start % sectors) {
234bc1e8f56SAndrey V. Elsukov *size += (*start % sectors) - sectors;
235bc1e8f56SAndrey V. Elsukov *start -= (*start % sectors) - sectors;
236bc1e8f56SAndrey V. Elsukov }
237bc1e8f56SAndrey V. Elsukov if (*size % sectors)
238bc1e8f56SAndrey V. Elsukov *size -= (*size % sectors);
239bc1e8f56SAndrey V. Elsukov if (*size < 2 * sectors)
240bc1e8f56SAndrey V. Elsukov return (EINVAL);
241bc1e8f56SAndrey V. Elsukov return (0);
242bc1e8f56SAndrey V. Elsukov }
243bc1e8f56SAndrey V. Elsukov
244bc1e8f56SAndrey V. Elsukov static int
g_part_ebr_add(struct g_part_table * basetable,struct g_part_entry * baseentry,struct g_part_parms * gpp)2455d68db5bSMarcel Moolenaar g_part_ebr_add(struct g_part_table *basetable, struct g_part_entry *baseentry,
2465d68db5bSMarcel Moolenaar struct g_part_parms *gpp)
2475d68db5bSMarcel Moolenaar {
248e24c8a3fSMarcel Moolenaar struct g_provider *pp;
249e24c8a3fSMarcel Moolenaar struct g_part_ebr_entry *entry;
25064612d4eSConrad Meyer struct g_part_entry *iter;
251bc1e8f56SAndrey V. Elsukov uint32_t start, size;
25264612d4eSConrad Meyer u_int idx;
2535d68db5bSMarcel Moolenaar
254e24c8a3fSMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_LABEL)
255e24c8a3fSMarcel Moolenaar return (EINVAL);
256e24c8a3fSMarcel Moolenaar
257bc1e8f56SAndrey V. Elsukov pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
258e24c8a3fSMarcel Moolenaar entry = (struct g_part_ebr_entry *)baseentry;
259e24c8a3fSMarcel Moolenaar start = gpp->gpp_start;
260e24c8a3fSMarcel Moolenaar size = gpp->gpp_size;
261bc1e8f56SAndrey V. Elsukov if (ebr_align(basetable, &start, &size) != 0)
262e24c8a3fSMarcel Moolenaar return (EINVAL);
263e24c8a3fSMarcel Moolenaar if (baseentry->gpe_deleted)
264e24c8a3fSMarcel Moolenaar bzero(&entry->ent, sizeof(entry->ent));
265e24c8a3fSMarcel Moolenaar
26642a783c1SRui Paulo KASSERT(baseentry->gpe_start <= start, ("%s", __func__));
26742a783c1SRui Paulo KASSERT(baseentry->gpe_end >= start + size - 1, ("%s", __func__));
268bc1e8f56SAndrey V. Elsukov baseentry->gpe_index = (start / basetable->gpt_sectors) + 1;
269bc1e8f56SAndrey V. Elsukov baseentry->gpe_offset =
270bc1e8f56SAndrey V. Elsukov (off_t)(start + basetable->gpt_sectors) * pp->sectorsize;
271e24c8a3fSMarcel Moolenaar baseentry->gpe_start = start;
272e24c8a3fSMarcel Moolenaar baseentry->gpe_end = start + size - 1;
273bc1e8f56SAndrey V. Elsukov entry->ent.dp_start = basetable->gpt_sectors;
274bc1e8f56SAndrey V. Elsukov entry->ent.dp_size = size - basetable->gpt_sectors;
275e24c8a3fSMarcel Moolenaar ebr_set_chs(basetable, entry->ent.dp_start, &entry->ent.dp_scyl,
276e24c8a3fSMarcel Moolenaar &entry->ent.dp_shd, &entry->ent.dp_ssect);
277e24c8a3fSMarcel Moolenaar ebr_set_chs(basetable, baseentry->gpe_end, &entry->ent.dp_ecyl,
278e24c8a3fSMarcel Moolenaar &entry->ent.dp_ehd, &entry->ent.dp_esect);
27964612d4eSConrad Meyer
28064612d4eSConrad Meyer idx = 5;
28164612d4eSConrad Meyer LIST_FOREACH(iter, &basetable->gpt_entry, gpe_entry)
28264612d4eSConrad Meyer idx++;
28364612d4eSConrad Meyer entry->ebr_compat_idx = idx;
284e24c8a3fSMarcel Moolenaar return (ebr_parse_type(gpp->gpp_type, &entry->ent.dp_typ));
2855d68db5bSMarcel Moolenaar }
2865d68db5bSMarcel Moolenaar
28764612d4eSConrad Meyer static void
g_part_ebr_add_alias(struct g_part_table * table,struct g_provider * pp,struct g_part_entry * baseentry,const char * pfx)28864612d4eSConrad Meyer g_part_ebr_add_alias(struct g_part_table *table, struct g_provider *pp,
28964612d4eSConrad Meyer struct g_part_entry *baseentry, const char *pfx)
29064612d4eSConrad Meyer {
29164612d4eSConrad Meyer struct g_part_ebr_entry *entry;
29264612d4eSConrad Meyer
29364612d4eSConrad Meyer g_provider_add_alias(pp, "%s%s" EBRNAMFMT, pfx, g_part_separator,
29464612d4eSConrad Meyer baseentry->gpe_index);
29564612d4eSConrad Meyer entry = (struct g_part_ebr_entry *)baseentry;
29664612d4eSConrad Meyer g_provider_add_alias(pp, "%.*s%u", (int)strlen(pfx) - 1, pfx,
29764612d4eSConrad Meyer entry->ebr_compat_idx);
29864612d4eSConrad Meyer }
29964612d4eSConrad Meyer
30064612d4eSConrad Meyer static struct g_provider *
g_part_ebr_new_provider(struct g_part_table * table,struct g_geom * gp,struct g_part_entry * baseentry,const char * pfx)30164612d4eSConrad Meyer g_part_ebr_new_provider(struct g_part_table *table, struct g_geom *gp,
30264612d4eSConrad Meyer struct g_part_entry *baseentry, const char *pfx)
30364612d4eSConrad Meyer {
30464612d4eSConrad Meyer struct g_part_ebr_entry *entry;
30564612d4eSConrad Meyer struct g_provider *pp;
30664612d4eSConrad Meyer
30764612d4eSConrad Meyer pp = g_new_providerf(gp, "%s%s" EBRNAMFMT, pfx, g_part_separator,
30864612d4eSConrad Meyer baseentry->gpe_index);
30964612d4eSConrad Meyer entry = (struct g_part_ebr_entry *)baseentry;
31064612d4eSConrad Meyer g_provider_add_alias(pp, "%.*s%u", (int)strlen(pfx) - 1, pfx,
31164612d4eSConrad Meyer entry->ebr_compat_idx);
31264612d4eSConrad Meyer return (pp);
31364612d4eSConrad Meyer }
31464612d4eSConrad Meyer
3155d68db5bSMarcel Moolenaar static int
g_part_ebr_create(struct g_part_table * basetable,struct g_part_parms * gpp)3165d68db5bSMarcel Moolenaar g_part_ebr_create(struct g_part_table *basetable, struct g_part_parms *gpp)
3175d68db5bSMarcel Moolenaar {
3183bcf7d71SAndrey V. Elsukov char type[64];
319e24c8a3fSMarcel Moolenaar struct g_consumer *cp;
320e24c8a3fSMarcel Moolenaar struct g_provider *pp;
321f5f875edSMarcel Moolenaar uint32_t msize;
322e24c8a3fSMarcel Moolenaar int error;
3235d68db5bSMarcel Moolenaar
324e24c8a3fSMarcel Moolenaar pp = gpp->gpp_provider;
325e24c8a3fSMarcel Moolenaar
326e24c8a3fSMarcel Moolenaar if (pp->sectorsize < EBRSIZE)
327e24c8a3fSMarcel Moolenaar return (ENOSPC);
328e24c8a3fSMarcel Moolenaar if (pp->sectorsize > 4096)
329e24c8a3fSMarcel Moolenaar return (ENXIO);
330e24c8a3fSMarcel Moolenaar
331e24c8a3fSMarcel Moolenaar /* Check that we have a parent and that it's a MBR. */
332e24c8a3fSMarcel Moolenaar if (basetable->gpt_depth == 0)
333e24c8a3fSMarcel Moolenaar return (ENXIO);
334e24c8a3fSMarcel Moolenaar cp = LIST_FIRST(&pp->consumers);
3353bcf7d71SAndrey V. Elsukov error = g_getattr("PART::scheme", cp, &type);
3363bcf7d71SAndrey V. Elsukov if (error != 0)
337e24c8a3fSMarcel Moolenaar return (error);
3383bcf7d71SAndrey V. Elsukov if (strcmp(type, "MBR") != 0)
3393bcf7d71SAndrey V. Elsukov return (ENXIO);
3403bcf7d71SAndrey V. Elsukov error = g_getattr("PART::type", cp, &type);
3413bcf7d71SAndrey V. Elsukov if (error != 0)
3423bcf7d71SAndrey V. Elsukov return (error);
3433bcf7d71SAndrey V. Elsukov if (strcmp(type, "ebr") != 0)
344e24c8a3fSMarcel Moolenaar return (ENXIO);
345e24c8a3fSMarcel Moolenaar
346284a82d0SAndrey V. Elsukov msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
347e24c8a3fSMarcel Moolenaar basetable->gpt_first = 0;
348f5f875edSMarcel Moolenaar basetable->gpt_last = msize - 1;
349f5f875edSMarcel Moolenaar basetable->gpt_entries = msize / basetable->gpt_sectors;
350e24c8a3fSMarcel Moolenaar return (0);
3515d68db5bSMarcel Moolenaar }
3525d68db5bSMarcel Moolenaar
3535d68db5bSMarcel Moolenaar static int
g_part_ebr_destroy(struct g_part_table * basetable,struct g_part_parms * gpp)3545d68db5bSMarcel Moolenaar g_part_ebr_destroy(struct g_part_table *basetable, struct g_part_parms *gpp)
3555d68db5bSMarcel Moolenaar {
3565d68db5bSMarcel Moolenaar
3575d68db5bSMarcel Moolenaar /* Wipe the first sector to clear the partitioning. */
3585d68db5bSMarcel Moolenaar basetable->gpt_smhead |= 1;
3595d68db5bSMarcel Moolenaar return (0);
3605d68db5bSMarcel Moolenaar }
3615d68db5bSMarcel Moolenaar
3625d68db5bSMarcel Moolenaar static void
g_part_ebr_dumpconf(struct g_part_table * table,struct g_part_entry * baseentry,struct sbuf * sb,const char * indent)3635d68db5bSMarcel Moolenaar g_part_ebr_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry,
3645d68db5bSMarcel Moolenaar struct sbuf *sb, const char *indent)
3655d68db5bSMarcel Moolenaar {
3665d68db5bSMarcel Moolenaar struct g_part_ebr_entry *entry;
3675d68db5bSMarcel Moolenaar
3685d68db5bSMarcel Moolenaar entry = (struct g_part_ebr_entry *)baseentry;
3695d68db5bSMarcel Moolenaar if (indent == NULL) {
3705d68db5bSMarcel Moolenaar /* conftxt: libdisk compatibility */
3715d68db5bSMarcel Moolenaar sbuf_printf(sb, " xs MBREXT xt %u", entry->ent.dp_typ);
3725d68db5bSMarcel Moolenaar } else if (entry != NULL) {
3735d68db5bSMarcel Moolenaar /* confxml: partition entry information */
3745d68db5bSMarcel Moolenaar sbuf_printf(sb, "%s<rawtype>%u</rawtype>\n", indent,
3755d68db5bSMarcel Moolenaar entry->ent.dp_typ);
3765d68db5bSMarcel Moolenaar if (entry->ent.dp_flag & 0x80)
3775d68db5bSMarcel Moolenaar sbuf_printf(sb, "%s<attrib>active</attrib>\n", indent);
3785d68db5bSMarcel Moolenaar } else {
3795d68db5bSMarcel Moolenaar /* confxml: scheme information */
3805d68db5bSMarcel Moolenaar }
3815d68db5bSMarcel Moolenaar }
3825d68db5bSMarcel Moolenaar
3835d68db5bSMarcel Moolenaar static int
g_part_ebr_dumpto(struct g_part_table * table,struct g_part_entry * baseentry)3845d68db5bSMarcel Moolenaar g_part_ebr_dumpto(struct g_part_table *table, struct g_part_entry *baseentry)
3855d68db5bSMarcel Moolenaar {
3865d68db5bSMarcel Moolenaar struct g_part_ebr_entry *entry;
3875d68db5bSMarcel Moolenaar
388b5bad281SDon Lewis /* Allow dumping to a FreeBSD partition or Linux swap partition only. */
3895d68db5bSMarcel Moolenaar entry = (struct g_part_ebr_entry *)baseentry;
390b5bad281SDon Lewis return ((entry->ent.dp_typ == DOSPTYP_386BSD ||
391b5bad281SDon Lewis entry->ent.dp_typ == DOSPTYP_LINSWP) ? 1 : 0);
3925d68db5bSMarcel Moolenaar }
3935d68db5bSMarcel Moolenaar
3945d68db5bSMarcel Moolenaar static int
g_part_ebr_modify(struct g_part_table * basetable,struct g_part_entry * baseentry,struct g_part_parms * gpp)3955d68db5bSMarcel Moolenaar g_part_ebr_modify(struct g_part_table *basetable,
3965d68db5bSMarcel Moolenaar struct g_part_entry *baseentry, struct g_part_parms *gpp)
3975d68db5bSMarcel Moolenaar {
398e24c8a3fSMarcel Moolenaar struct g_part_ebr_entry *entry;
3995d68db5bSMarcel Moolenaar
400e24c8a3fSMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_LABEL)
401e24c8a3fSMarcel Moolenaar return (EINVAL);
402e24c8a3fSMarcel Moolenaar
403e24c8a3fSMarcel Moolenaar entry = (struct g_part_ebr_entry *)baseentry;
404e24c8a3fSMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_TYPE)
405e24c8a3fSMarcel Moolenaar return (ebr_parse_type(gpp->gpp_type, &entry->ent.dp_typ));
406e24c8a3fSMarcel Moolenaar return (0);
4075d68db5bSMarcel Moolenaar }
4085d68db5bSMarcel Moolenaar
409884c8e4fSAndrey V. Elsukov static int
g_part_ebr_resize(struct g_part_table * basetable,struct g_part_entry * baseentry,struct g_part_parms * gpp)410884c8e4fSAndrey V. Elsukov g_part_ebr_resize(struct g_part_table *basetable,
411884c8e4fSAndrey V. Elsukov struct g_part_entry *baseentry, struct g_part_parms *gpp)
412884c8e4fSAndrey V. Elsukov {
413884c8e4fSAndrey V. Elsukov struct g_provider *pp;
414884c8e4fSAndrey V. Elsukov
415884c8e4fSAndrey V. Elsukov if (baseentry != NULL)
416884c8e4fSAndrey V. Elsukov return (EOPNOTSUPP);
417884c8e4fSAndrey V. Elsukov pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
418884c8e4fSAndrey V. Elsukov basetable->gpt_last = MIN(pp->mediasize / pp->sectorsize,
419884c8e4fSAndrey V. Elsukov UINT32_MAX) - 1;
420884c8e4fSAndrey V. Elsukov return (0);
421884c8e4fSAndrey V. Elsukov }
422884c8e4fSAndrey V. Elsukov
4235d68db5bSMarcel Moolenaar static const char *
g_part_ebr_name(struct g_part_table * table,struct g_part_entry * entry,char * buf,size_t bufsz)4245d68db5bSMarcel Moolenaar g_part_ebr_name(struct g_part_table *table, struct g_part_entry *entry,
4255d68db5bSMarcel Moolenaar char *buf, size_t bufsz)
4265d68db5bSMarcel Moolenaar {
42764612d4eSConrad Meyer snprintf(buf, bufsz, EBRNAMFMT, entry->gpe_index);
4285d68db5bSMarcel Moolenaar return (buf);
4295d68db5bSMarcel Moolenaar }
4305d68db5bSMarcel Moolenaar
4315d68db5bSMarcel Moolenaar static int
g_part_ebr_precheck(struct g_part_table * table,enum g_part_ctl req,struct g_part_parms * gpp)432e24c8a3fSMarcel Moolenaar g_part_ebr_precheck(struct g_part_table *table, enum g_part_ctl req,
433e24c8a3fSMarcel Moolenaar struct g_part_parms *gpp)
434e24c8a3fSMarcel Moolenaar {
435e24c8a3fSMarcel Moolenaar /*
436e24c8a3fSMarcel Moolenaar * The index is a function of the start of the partition.
437e24c8a3fSMarcel Moolenaar * This is not something the user can override, nor is it
438e24c8a3fSMarcel Moolenaar * something the common code will do right. We can set the
439e24c8a3fSMarcel Moolenaar * index now so that we get what we need.
440e24c8a3fSMarcel Moolenaar */
441e24c8a3fSMarcel Moolenaar if (req == G_PART_CTL_ADD)
442e24c8a3fSMarcel Moolenaar gpp->gpp_index = (gpp->gpp_start / table->gpt_sectors) + 1;
443e24c8a3fSMarcel Moolenaar return (0);
444e24c8a3fSMarcel Moolenaar }
445e24c8a3fSMarcel Moolenaar
446e24c8a3fSMarcel Moolenaar static int
g_part_ebr_probe(struct g_part_table * table,struct g_consumer * cp)4475d68db5bSMarcel Moolenaar g_part_ebr_probe(struct g_part_table *table, struct g_consumer *cp)
4485d68db5bSMarcel Moolenaar {
4493bcf7d71SAndrey V. Elsukov char type[64];
4505d68db5bSMarcel Moolenaar struct g_provider *pp;
4515d68db5bSMarcel Moolenaar u_char *buf, *p;
452d3507dffSAndrey V. Elsukov int error, index, res;
4535d68db5bSMarcel Moolenaar uint16_t magic;
4545d68db5bSMarcel Moolenaar
4555d68db5bSMarcel Moolenaar pp = cp->provider;
4565d68db5bSMarcel Moolenaar
4575d68db5bSMarcel Moolenaar /* Sanity-check the provider. */
4585d68db5bSMarcel Moolenaar if (pp->sectorsize < EBRSIZE || pp->mediasize < pp->sectorsize)
4595d68db5bSMarcel Moolenaar return (ENOSPC);
4605d68db5bSMarcel Moolenaar if (pp->sectorsize > 4096)
4615d68db5bSMarcel Moolenaar return (ENXIO);
4625d68db5bSMarcel Moolenaar
4635d68db5bSMarcel Moolenaar /* Check that we have a parent and that it's a MBR. */
4645d68db5bSMarcel Moolenaar if (table->gpt_depth == 0)
4655d68db5bSMarcel Moolenaar return (ENXIO);
4663bcf7d71SAndrey V. Elsukov error = g_getattr("PART::scheme", cp, &type);
4673bcf7d71SAndrey V. Elsukov if (error != 0)
4685d68db5bSMarcel Moolenaar return (error);
4693bcf7d71SAndrey V. Elsukov if (strcmp(type, "MBR") != 0)
4703bcf7d71SAndrey V. Elsukov return (ENXIO);
4713bcf7d71SAndrey V. Elsukov /* Check that partition has type DOSPTYP_EBR. */
4723bcf7d71SAndrey V. Elsukov error = g_getattr("PART::type", cp, &type);
4733bcf7d71SAndrey V. Elsukov if (error != 0)
4743bcf7d71SAndrey V. Elsukov return (error);
4753bcf7d71SAndrey V. Elsukov if (strcmp(type, "ebr") != 0)
4765d68db5bSMarcel Moolenaar return (ENXIO);
4775d68db5bSMarcel Moolenaar
4785d68db5bSMarcel Moolenaar /* Check that there's a EBR. */
4795d68db5bSMarcel Moolenaar buf = g_read_data(cp, 0L, pp->sectorsize, &error);
4805d68db5bSMarcel Moolenaar if (buf == NULL)
4815d68db5bSMarcel Moolenaar return (error);
4825d68db5bSMarcel Moolenaar
4835d68db5bSMarcel Moolenaar /* We goto out on mismatch. */
4845d68db5bSMarcel Moolenaar res = ENXIO;
4855d68db5bSMarcel Moolenaar
4865d68db5bSMarcel Moolenaar magic = le16dec(buf + DOSMAGICOFFSET);
4875d68db5bSMarcel Moolenaar if (magic != DOSMAGIC)
4885d68db5bSMarcel Moolenaar goto out;
4895d68db5bSMarcel Moolenaar
490d3507dffSAndrey V. Elsukov for (index = 0; index < 2; index++) {
4915d68db5bSMarcel Moolenaar p = buf + DOSPARTOFF + index * DOSPARTSIZE;
4925d68db5bSMarcel Moolenaar if (p[0] != 0 && p[0] != 0x80)
4935d68db5bSMarcel Moolenaar goto out;
4945d68db5bSMarcel Moolenaar }
495f3548c02SMarcel Moolenaar res = G_PART_PROBE_PRI_NORM;
4965d68db5bSMarcel Moolenaar
4975d68db5bSMarcel Moolenaar out:
4985d68db5bSMarcel Moolenaar g_free(buf);
4995d68db5bSMarcel Moolenaar return (res);
5005d68db5bSMarcel Moolenaar }
5015d68db5bSMarcel Moolenaar
5025d68db5bSMarcel Moolenaar static int
g_part_ebr_read(struct g_part_table * basetable,struct g_consumer * cp)5035d68db5bSMarcel Moolenaar g_part_ebr_read(struct g_part_table *basetable, struct g_consumer *cp)
5045d68db5bSMarcel Moolenaar {
5055d68db5bSMarcel Moolenaar struct dos_partition ent[2];
5065d68db5bSMarcel Moolenaar struct g_provider *pp;
5075d68db5bSMarcel Moolenaar struct g_part_entry *baseentry;
5085d68db5bSMarcel Moolenaar struct g_part_ebr_table *table;
5095d68db5bSMarcel Moolenaar struct g_part_ebr_entry *entry;
5105d68db5bSMarcel Moolenaar u_char *buf;
5115d68db5bSMarcel Moolenaar off_t ofs, msize;
51264612d4eSConrad Meyer u_int lba, idx;
513671dfdbfSAndrey V. Elsukov int error, index;
5145d68db5bSMarcel Moolenaar
51564612d4eSConrad Meyer idx = 5;
5165d68db5bSMarcel Moolenaar pp = cp->provider;
5175d68db5bSMarcel Moolenaar table = (struct g_part_ebr_table *)basetable;
518284a82d0SAndrey V. Elsukov msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
5195d68db5bSMarcel Moolenaar
5205d68db5bSMarcel Moolenaar lba = 0;
5215d68db5bSMarcel Moolenaar while (1) {
5225d68db5bSMarcel Moolenaar ofs = (off_t)lba * pp->sectorsize;
5235d68db5bSMarcel Moolenaar buf = g_read_data(cp, ofs, pp->sectorsize, &error);
5245d68db5bSMarcel Moolenaar if (buf == NULL)
5255d68db5bSMarcel Moolenaar return (error);
5265d68db5bSMarcel Moolenaar
5275d68db5bSMarcel Moolenaar ebr_entry_decode(buf + DOSPARTOFF + 0 * DOSPARTSIZE, ent + 0);
5285d68db5bSMarcel Moolenaar ebr_entry_decode(buf + DOSPARTOFF + 1 * DOSPARTSIZE, ent + 1);
529d3507dffSAndrey V. Elsukov
530d3507dffSAndrey V. Elsukov /* The 3rd & 4th entries should be zeroes. */
531d3507dffSAndrey V. Elsukov if (le64dec(buf + DOSPARTOFF + 2 * DOSPARTSIZE) +
532d3507dffSAndrey V. Elsukov le64dec(buf + DOSPARTOFF + 3 * DOSPARTSIZE) != 0) {
533d3507dffSAndrey V. Elsukov basetable->gpt_corrupt = 1;
534d3507dffSAndrey V. Elsukov printf("GEOM: %s: invalid entries in the EBR ignored.\n",
535d3507dffSAndrey V. Elsukov pp->name);
536d3507dffSAndrey V. Elsukov }
53764612d4eSConrad Meyer /*
53864612d4eSConrad Meyer * Preserve EBR, it can contain boot code or other metadata we
53964612d4eSConrad Meyer * are ignorant of.
54064612d4eSConrad Meyer */
541671dfdbfSAndrey V. Elsukov if (lba == 0)
54264612d4eSConrad Meyer memcpy(table->lba0_ebr, buf, sizeof(table->lba0_ebr));
5435d68db5bSMarcel Moolenaar
54464612d4eSConrad Meyer if (ent[0].dp_typ == 0) {
54564612d4eSConrad Meyer g_free(buf);
5465d68db5bSMarcel Moolenaar break;
54764612d4eSConrad Meyer }
5485d68db5bSMarcel Moolenaar
5495d68db5bSMarcel Moolenaar if (ent[0].dp_typ == 5 && ent[1].dp_typ == 0) {
5505d68db5bSMarcel Moolenaar lba = ent[0].dp_start;
55164612d4eSConrad Meyer g_free(buf);
5525d68db5bSMarcel Moolenaar continue;
5535d68db5bSMarcel Moolenaar }
5545d68db5bSMarcel Moolenaar
5555d68db5bSMarcel Moolenaar index = (lba / basetable->gpt_sectors) + 1;
5565d68db5bSMarcel Moolenaar baseentry = (struct g_part_entry *)g_part_new_entry(basetable,
5575d68db5bSMarcel Moolenaar index, lba, lba + ent[0].dp_start + ent[0].dp_size - 1);
5585d68db5bSMarcel Moolenaar baseentry->gpe_offset = (off_t)(lba + ent[0].dp_start) *
5595d68db5bSMarcel Moolenaar pp->sectorsize;
5605d68db5bSMarcel Moolenaar entry = (struct g_part_ebr_entry *)baseentry;
5615d68db5bSMarcel Moolenaar entry->ent = ent[0];
56264612d4eSConrad Meyer memcpy(entry->ebr, buf, sizeof(entry->ebr));
56364612d4eSConrad Meyer entry->ebr_compat_idx = idx++;
56464612d4eSConrad Meyer g_free(buf);
5655d68db5bSMarcel Moolenaar
5665d68db5bSMarcel Moolenaar if (ent[1].dp_typ == 0)
5675d68db5bSMarcel Moolenaar break;
5685d68db5bSMarcel Moolenaar
5695d68db5bSMarcel Moolenaar lba = ent[1].dp_start;
5705d68db5bSMarcel Moolenaar }
5715d68db5bSMarcel Moolenaar
5725d68db5bSMarcel Moolenaar basetable->gpt_entries = msize / basetable->gpt_sectors;
5735d68db5bSMarcel Moolenaar basetable->gpt_first = 0;
57423a34900SAndrey V. Elsukov basetable->gpt_last = msize - 1;
5755d68db5bSMarcel Moolenaar return (0);
5765d68db5bSMarcel Moolenaar }
5775d68db5bSMarcel Moolenaar
5785d68db5bSMarcel Moolenaar static int
g_part_ebr_setunset(struct g_part_table * table,struct g_part_entry * baseentry,const char * attrib,unsigned int set)5795d68db5bSMarcel Moolenaar g_part_ebr_setunset(struct g_part_table *table, struct g_part_entry *baseentry,
5805d68db5bSMarcel Moolenaar const char *attrib, unsigned int set)
5815d68db5bSMarcel Moolenaar {
582e24c8a3fSMarcel Moolenaar struct g_part_entry *iter;
583e24c8a3fSMarcel Moolenaar struct g_part_ebr_entry *entry;
584e24c8a3fSMarcel Moolenaar int changed;
5855d68db5bSMarcel Moolenaar
5863bd22a9cSMarcel Moolenaar if (baseentry == NULL)
5873bd22a9cSMarcel Moolenaar return (ENODEV);
588e24c8a3fSMarcel Moolenaar if (strcasecmp(attrib, "active") != 0)
589e24c8a3fSMarcel Moolenaar return (EINVAL);
590e24c8a3fSMarcel Moolenaar
591e24c8a3fSMarcel Moolenaar /* Only one entry can have the active attribute. */
592e24c8a3fSMarcel Moolenaar LIST_FOREACH(iter, &table->gpt_entry, gpe_entry) {
593e24c8a3fSMarcel Moolenaar if (iter->gpe_deleted)
594e24c8a3fSMarcel Moolenaar continue;
595e24c8a3fSMarcel Moolenaar changed = 0;
596e24c8a3fSMarcel Moolenaar entry = (struct g_part_ebr_entry *)iter;
597e24c8a3fSMarcel Moolenaar if (iter == baseentry) {
598e24c8a3fSMarcel Moolenaar if (set && (entry->ent.dp_flag & 0x80) == 0) {
599e24c8a3fSMarcel Moolenaar entry->ent.dp_flag |= 0x80;
600e24c8a3fSMarcel Moolenaar changed = 1;
601e24c8a3fSMarcel Moolenaar } else if (!set && (entry->ent.dp_flag & 0x80)) {
602e24c8a3fSMarcel Moolenaar entry->ent.dp_flag &= ~0x80;
603e24c8a3fSMarcel Moolenaar changed = 1;
604e24c8a3fSMarcel Moolenaar }
605e24c8a3fSMarcel Moolenaar } else {
606e24c8a3fSMarcel Moolenaar if (set && (entry->ent.dp_flag & 0x80)) {
607e24c8a3fSMarcel Moolenaar entry->ent.dp_flag &= ~0x80;
608e24c8a3fSMarcel Moolenaar changed = 1;
609e24c8a3fSMarcel Moolenaar }
610e24c8a3fSMarcel Moolenaar }
611e24c8a3fSMarcel Moolenaar if (changed && !iter->gpe_created)
612e24c8a3fSMarcel Moolenaar iter->gpe_modified = 1;
613e24c8a3fSMarcel Moolenaar }
614e24c8a3fSMarcel Moolenaar return (0);
6155d68db5bSMarcel Moolenaar }
6165d68db5bSMarcel Moolenaar
6175d68db5bSMarcel Moolenaar static const char *
g_part_ebr_type(struct g_part_table * basetable,struct g_part_entry * baseentry,char * buf,size_t bufsz)6185d68db5bSMarcel Moolenaar g_part_ebr_type(struct g_part_table *basetable, struct g_part_entry *baseentry,
6195d68db5bSMarcel Moolenaar char *buf, size_t bufsz)
6205d68db5bSMarcel Moolenaar {
6215d68db5bSMarcel Moolenaar struct g_part_ebr_entry *entry;
62288007f61SAndrey V. Elsukov int i;
6235d68db5bSMarcel Moolenaar
6245d68db5bSMarcel Moolenaar entry = (struct g_part_ebr_entry *)baseentry;
62563b6b7a7SPedro F. Giffuni for (i = 0; i < nitems(ebr_alias_match); i++) {
62688007f61SAndrey V. Elsukov if (ebr_alias_match[i].typ == entry->ent.dp_typ)
62788007f61SAndrey V. Elsukov return (g_part_alias_name(ebr_alias_match[i].alias));
62888007f61SAndrey V. Elsukov }
62988007f61SAndrey V. Elsukov snprintf(buf, bufsz, "!%d", entry->ent.dp_typ);
6305d68db5bSMarcel Moolenaar return (buf);
6315d68db5bSMarcel Moolenaar }
6325d68db5bSMarcel Moolenaar
6335d68db5bSMarcel Moolenaar static int
g_part_ebr_write(struct g_part_table * basetable,struct g_consumer * cp)6345d68db5bSMarcel Moolenaar g_part_ebr_write(struct g_part_table *basetable, struct g_consumer *cp)
6355d68db5bSMarcel Moolenaar {
636671dfdbfSAndrey V. Elsukov struct g_part_ebr_table *table;
637e24c8a3fSMarcel Moolenaar struct g_provider *pp;
638e24c8a3fSMarcel Moolenaar struct g_part_entry *baseentry, *next;
639e24c8a3fSMarcel Moolenaar struct g_part_ebr_entry *entry;
640e24c8a3fSMarcel Moolenaar u_char *buf;
641e24c8a3fSMarcel Moolenaar u_char *p;
642e24c8a3fSMarcel Moolenaar int error;
6435d68db5bSMarcel Moolenaar
644e24c8a3fSMarcel Moolenaar pp = cp->provider;
645e24c8a3fSMarcel Moolenaar buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO);
646671dfdbfSAndrey V. Elsukov table = (struct g_part_ebr_table *)basetable;
64764612d4eSConrad Meyer
64864612d4eSConrad Meyer _Static_assert(DOSPARTOFF <= sizeof(table->lba0_ebr), "");
64964612d4eSConrad Meyer memcpy(buf, table->lba0_ebr, DOSPARTOFF);
650e24c8a3fSMarcel Moolenaar le16enc(buf + DOSMAGICOFFSET, DOSMAGIC);
651e24c8a3fSMarcel Moolenaar
652e24c8a3fSMarcel Moolenaar baseentry = LIST_FIRST(&basetable->gpt_entry);
653e24c8a3fSMarcel Moolenaar while (baseentry != NULL && baseentry->gpe_deleted)
654e24c8a3fSMarcel Moolenaar baseentry = LIST_NEXT(baseentry, gpe_entry);
655e24c8a3fSMarcel Moolenaar
6566bccea7cSRebecca Cran /* Wipe-out the first EBR when there are no slices. */
657e24c8a3fSMarcel Moolenaar if (baseentry == NULL) {
658e24c8a3fSMarcel Moolenaar error = g_write_data(cp, 0, buf, pp->sectorsize);
659e24c8a3fSMarcel Moolenaar goto out;
660e24c8a3fSMarcel Moolenaar }
661e24c8a3fSMarcel Moolenaar
662e24c8a3fSMarcel Moolenaar /*
663e24c8a3fSMarcel Moolenaar * If the first partition is not in LBA 0, we need to
664e24c8a3fSMarcel Moolenaar * put a "link" EBR in LBA 0.
665e24c8a3fSMarcel Moolenaar */
666e24c8a3fSMarcel Moolenaar if (baseentry->gpe_start != 0) {
667e24c8a3fSMarcel Moolenaar ebr_entry_link(basetable, (uint32_t)baseentry->gpe_start,
668e24c8a3fSMarcel Moolenaar (uint32_t)baseentry->gpe_end, buf + DOSPARTOFF);
669e24c8a3fSMarcel Moolenaar error = g_write_data(cp, 0, buf, pp->sectorsize);
670e24c8a3fSMarcel Moolenaar if (error)
671e24c8a3fSMarcel Moolenaar goto out;
672e24c8a3fSMarcel Moolenaar }
673e24c8a3fSMarcel Moolenaar
674e24c8a3fSMarcel Moolenaar do {
675e24c8a3fSMarcel Moolenaar entry = (struct g_part_ebr_entry *)baseentry;
676e24c8a3fSMarcel Moolenaar
67764612d4eSConrad Meyer _Static_assert(DOSPARTOFF <= sizeof(entry->ebr), "");
67864612d4eSConrad Meyer memcpy(buf, entry->ebr, DOSPARTOFF);
67964612d4eSConrad Meyer
680e24c8a3fSMarcel Moolenaar p = buf + DOSPARTOFF;
681e24c8a3fSMarcel Moolenaar p[0] = entry->ent.dp_flag;
682e24c8a3fSMarcel Moolenaar p[1] = entry->ent.dp_shd;
683e24c8a3fSMarcel Moolenaar p[2] = entry->ent.dp_ssect;
684e24c8a3fSMarcel Moolenaar p[3] = entry->ent.dp_scyl;
685e24c8a3fSMarcel Moolenaar p[4] = entry->ent.dp_typ;
686e24c8a3fSMarcel Moolenaar p[5] = entry->ent.dp_ehd;
687e24c8a3fSMarcel Moolenaar p[6] = entry->ent.dp_esect;
688e24c8a3fSMarcel Moolenaar p[7] = entry->ent.dp_ecyl;
689e24c8a3fSMarcel Moolenaar le32enc(p + 8, entry->ent.dp_start);
690e24c8a3fSMarcel Moolenaar le32enc(p + 12, entry->ent.dp_size);
691e24c8a3fSMarcel Moolenaar
692e24c8a3fSMarcel Moolenaar next = LIST_NEXT(baseentry, gpe_entry);
693507a0d4aSMarcel Moolenaar while (next != NULL && next->gpe_deleted)
694507a0d4aSMarcel Moolenaar next = LIST_NEXT(next, gpe_entry);
695e24c8a3fSMarcel Moolenaar
696e24c8a3fSMarcel Moolenaar p += DOSPARTSIZE;
697e24c8a3fSMarcel Moolenaar if (next != NULL)
698e24c8a3fSMarcel Moolenaar ebr_entry_link(basetable, (uint32_t)next->gpe_start,
699e24c8a3fSMarcel Moolenaar (uint32_t)next->gpe_end, p);
700e24c8a3fSMarcel Moolenaar else
701e24c8a3fSMarcel Moolenaar bzero(p, DOSPARTSIZE);
702e24c8a3fSMarcel Moolenaar
703e24c8a3fSMarcel Moolenaar error = g_write_data(cp, baseentry->gpe_start * pp->sectorsize,
704e24c8a3fSMarcel Moolenaar buf, pp->sectorsize);
705e24c8a3fSMarcel Moolenaar baseentry = next;
706e24c8a3fSMarcel Moolenaar } while (!error && baseentry != NULL);
707e24c8a3fSMarcel Moolenaar
708e24c8a3fSMarcel Moolenaar out:
709e24c8a3fSMarcel Moolenaar g_free(buf);
710e24c8a3fSMarcel Moolenaar return (error);
7115d68db5bSMarcel Moolenaar }
712