The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/geom/part/g_part_ebr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2007-2009 Marcel Moolenaar
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  *
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include "opt_geom.h"
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/8.0/sys/geom/part/g_part_ebr.c 191134 2009-04-16 05:52:47Z marcel $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/bio.h>
   34 #include <sys/diskmbr.h>
   35 #include <sys/endian.h>
   36 #include <sys/kernel.h>
   37 #include <sys/kobj.h>
   38 #include <sys/limits.h>
   39 #include <sys/lock.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mutex.h>
   42 #include <sys/queue.h>
   43 #include <sys/sbuf.h>
   44 #include <sys/systm.h>
   45 #include <geom/geom.h>
   46 #include <geom/part/g_part.h>
   47 
   48 #include "g_part_if.h"
   49 
   50 #define EBRSIZE         512
   51 
   52 struct g_part_ebr_table {
   53         struct g_part_table     base;
   54 };
   55 
   56 struct g_part_ebr_entry {
   57         struct g_part_entry     base;
   58         struct dos_partition    ent;
   59 };
   60 
   61 static int g_part_ebr_add(struct g_part_table *, struct g_part_entry *,
   62     struct g_part_parms *);
   63 static int g_part_ebr_create(struct g_part_table *, struct g_part_parms *);
   64 static int g_part_ebr_destroy(struct g_part_table *, struct g_part_parms *);
   65 static void g_part_ebr_dumpconf(struct g_part_table *, struct g_part_entry *,
   66     struct sbuf *, const char *);
   67 static int g_part_ebr_dumpto(struct g_part_table *, struct g_part_entry *);
   68 #if defined(GEOM_PART_EBR_COMPAT)
   69 static void g_part_ebr_fullname(struct g_part_table *, struct g_part_entry *,
   70     struct sbuf *, const char *);
   71 #endif
   72 static int g_part_ebr_modify(struct g_part_table *, struct g_part_entry *,  
   73     struct g_part_parms *);
   74 static const char *g_part_ebr_name(struct g_part_table *, struct g_part_entry *,
   75     char *, size_t);
   76 static int g_part_ebr_precheck(struct g_part_table *, enum g_part_ctl,
   77     struct g_part_parms *);
   78 static int g_part_ebr_probe(struct g_part_table *, struct g_consumer *);
   79 static int g_part_ebr_read(struct g_part_table *, struct g_consumer *);
   80 static int g_part_ebr_setunset(struct g_part_table *, struct g_part_entry *,
   81     const char *, unsigned int);
   82 static const char *g_part_ebr_type(struct g_part_table *, struct g_part_entry *,
   83     char *, size_t);
   84 static int g_part_ebr_write(struct g_part_table *, struct g_consumer *);
   85 
   86 static kobj_method_t g_part_ebr_methods[] = {
   87         KOBJMETHOD(g_part_add,          g_part_ebr_add),
   88         KOBJMETHOD(g_part_create,       g_part_ebr_create),
   89         KOBJMETHOD(g_part_destroy,      g_part_ebr_destroy),
   90         KOBJMETHOD(g_part_dumpconf,     g_part_ebr_dumpconf),
   91         KOBJMETHOD(g_part_dumpto,       g_part_ebr_dumpto),
   92 #if defined(GEOM_PART_EBR_COMPAT)
   93         KOBJMETHOD(g_part_fullname,     g_part_ebr_fullname),
   94 #endif
   95         KOBJMETHOD(g_part_modify,       g_part_ebr_modify),
   96         KOBJMETHOD(g_part_name,         g_part_ebr_name),
   97         KOBJMETHOD(g_part_precheck,     g_part_ebr_precheck),
   98         KOBJMETHOD(g_part_probe,        g_part_ebr_probe),
   99         KOBJMETHOD(g_part_read,         g_part_ebr_read),
  100         KOBJMETHOD(g_part_setunset,     g_part_ebr_setunset),
  101         KOBJMETHOD(g_part_type,         g_part_ebr_type),
  102         KOBJMETHOD(g_part_write,        g_part_ebr_write),
  103         { 0, 0 }
  104 };
  105 
  106 static struct g_part_scheme g_part_ebr_scheme = {
  107         "EBR",
  108         g_part_ebr_methods,
  109         sizeof(struct g_part_ebr_table),
  110         .gps_entrysz = sizeof(struct g_part_ebr_entry),
  111         .gps_minent = 1,
  112         .gps_maxent = INT_MAX,
  113 };
  114 G_PART_SCHEME_DECLARE(g_part_ebr);
  115 
  116 static void ebr_set_chs(struct g_part_table *, uint32_t, u_char *, u_char *,
  117     u_char *);
  118 
  119 static void
  120 ebr_entry_decode(const char *p, struct dos_partition *ent)
  121 {
  122         ent->dp_flag = p[0];
  123         ent->dp_shd = p[1];
  124         ent->dp_ssect = p[2];
  125         ent->dp_scyl = p[3];
  126         ent->dp_typ = p[4];
  127         ent->dp_ehd = p[5];
  128         ent->dp_esect = p[6];
  129         ent->dp_ecyl = p[7];
  130         ent->dp_start = le32dec(p + 8);
  131         ent->dp_size = le32dec(p + 12);
  132 }
  133 
  134 static void
  135 ebr_entry_link(struct g_part_table *table, uint32_t start, uint32_t end,
  136    u_char *buf)
  137 {
  138 
  139         buf[0] = 0 /* dp_flag */;
  140         ebr_set_chs(table, start, &buf[3] /* dp_scyl */, &buf[1] /* dp_shd */,
  141             &buf[2] /* dp_ssect */);
  142         buf[4] = 5 /* dp_typ */;
  143         ebr_set_chs(table, end, &buf[7] /* dp_ecyl */, &buf[5] /* dp_ehd */,
  144             &buf[6] /* dp_esect */);
  145         le32enc(buf + 8, start);
  146         le32enc(buf + 12, end - start + 1);
  147 }
  148 
  149 static int
  150 ebr_parse_type(const char *type, u_char *dp_typ)
  151 {
  152         const char *alias;
  153         char *endp;
  154         long lt;
  155 
  156         if (type[0] == '!') {
  157                 lt = strtol(type + 1, &endp, 0);
  158                 if (type[1] == '\0' || *endp != '\0' || lt <= 0 || lt >= 256)
  159                         return (EINVAL);
  160                 *dp_typ = (u_char)lt;
  161                 return (0);
  162         }
  163         alias = g_part_alias_name(G_PART_ALIAS_FREEBSD);
  164         if (!strcasecmp(type, alias)) {
  165                 *dp_typ = DOSPTYP_386BSD;
  166                 return (0);
  167         }
  168         return (EINVAL);
  169 }
  170 
  171 static void
  172 ebr_set_chs(struct g_part_table *table, uint32_t lba, u_char *cylp, u_char *hdp,
  173     u_char *secp)
  174 {
  175         uint32_t cyl, hd, sec;
  176 
  177         sec = lba % table->gpt_sectors + 1;
  178         lba /= table->gpt_sectors;
  179         hd = lba % table->gpt_heads;
  180         lba /= table->gpt_heads;
  181         cyl = lba;
  182         if (cyl > 1023)
  183                 sec = hd = cyl = ~0;
  184 
  185         *cylp = cyl & 0xff;
  186         *hdp = hd & 0xff;
  187         *secp = (sec & 0x3f) | ((cyl >> 2) & 0xc0);
  188 }
  189 
  190 static int
  191 g_part_ebr_add(struct g_part_table *basetable, struct g_part_entry *baseentry,
  192     struct g_part_parms *gpp)
  193 {
  194         struct g_geom *gp;
  195         struct g_provider *pp;
  196         struct g_part_ebr_entry *entry;
  197         uint32_t start, size, sectors;
  198 
  199         if (gpp->gpp_parms & G_PART_PARM_LABEL)
  200                 return (EINVAL);
  201 
  202         gp = basetable->gpt_gp;
  203         pp = LIST_FIRST(&gp->consumer)->provider;
  204         sectors = basetable->gpt_sectors;
  205 
  206         entry = (struct g_part_ebr_entry *)baseentry;
  207 
  208         start = gpp->gpp_start;
  209         size = gpp->gpp_size;
  210         if (size < 2 * sectors)
  211                 return (EINVAL);
  212         if (start % sectors) {
  213                 size = size - sectors + (start % sectors);
  214                 start = start - (start % sectors) + sectors;
  215         }
  216         if (size % sectors)
  217                 size = size - (size % sectors);
  218         if (size < 2 * sectors)
  219                 return (EINVAL);
  220 
  221         if (baseentry->gpe_deleted)
  222                 bzero(&entry->ent, sizeof(entry->ent));
  223 
  224         KASSERT(baseentry->gpe_start <= start, (__func__));
  225         KASSERT(baseentry->gpe_end >= start + size - 1, (__func__));
  226         baseentry->gpe_index = (start / sectors) + 1;
  227         baseentry->gpe_offset = (off_t)(start + sectors) * pp->sectorsize;
  228         baseentry->gpe_start = start;
  229         baseentry->gpe_end = start + size - 1;
  230         entry->ent.dp_start = sectors;
  231         entry->ent.dp_size = size - sectors;
  232         ebr_set_chs(basetable, entry->ent.dp_start, &entry->ent.dp_scyl,
  233             &entry->ent.dp_shd, &entry->ent.dp_ssect);
  234         ebr_set_chs(basetable, baseentry->gpe_end, &entry->ent.dp_ecyl,
  235             &entry->ent.dp_ehd, &entry->ent.dp_esect);
  236         return (ebr_parse_type(gpp->gpp_type, &entry->ent.dp_typ));
  237 }
  238 
  239 static int
  240 g_part_ebr_create(struct g_part_table *basetable, struct g_part_parms *gpp)
  241 {
  242         char psn[8];
  243         struct g_consumer *cp;
  244         struct g_provider *pp;
  245         uint32_t msize;
  246         int error;
  247 
  248         pp = gpp->gpp_provider;
  249 
  250         if (pp->sectorsize < EBRSIZE)
  251                 return (ENOSPC);
  252         if (pp->sectorsize > 4096)
  253                 return (ENXIO);
  254 
  255         /* Check that we have a parent and that it's a MBR. */
  256         if (basetable->gpt_depth == 0)
  257                 return (ENXIO);
  258         cp = LIST_FIRST(&pp->consumers);
  259         error = g_getattr("PART::scheme", cp, &psn);
  260         if (error)
  261                 return (error);
  262         if (strcmp(psn, "MBR"))
  263                 return (ENXIO);
  264 
  265         msize = MIN(pp->mediasize / pp->sectorsize, 0xffffffff);
  266         msize -= msize % basetable->gpt_sectors;
  267         basetable->gpt_first = 0;
  268         basetable->gpt_last = msize - 1;
  269         basetable->gpt_entries = msize / basetable->gpt_sectors;
  270         return (0);
  271 }
  272 
  273 static int
  274 g_part_ebr_destroy(struct g_part_table *basetable, struct g_part_parms *gpp)
  275 {
  276 
  277         /* Wipe the first sector to clear the partitioning. */
  278         basetable->gpt_smhead |= 1;
  279         return (0);
  280 }
  281 
  282 static void
  283 g_part_ebr_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry, 
  284     struct sbuf *sb, const char *indent)
  285 {
  286         struct g_part_ebr_entry *entry;
  287  
  288         entry = (struct g_part_ebr_entry *)baseentry;
  289         if (indent == NULL) {
  290                 /* conftxt: libdisk compatibility */
  291                 sbuf_printf(sb, " xs MBREXT xt %u", entry->ent.dp_typ);
  292         } else if (entry != NULL) {
  293                 /* confxml: partition entry information */
  294                 sbuf_printf(sb, "%s<rawtype>%u</rawtype>\n", indent,
  295                     entry->ent.dp_typ);
  296                 if (entry->ent.dp_flag & 0x80)
  297                         sbuf_printf(sb, "%s<attrib>active</attrib>\n", indent);
  298         } else {
  299                 /* confxml: scheme information */
  300         }
  301 }
  302 
  303 static int
  304 g_part_ebr_dumpto(struct g_part_table *table, struct g_part_entry *baseentry)  
  305 {
  306         struct g_part_ebr_entry *entry;
  307 
  308         /* Allow dumping to a FreeBSD partition only. */
  309         entry = (struct g_part_ebr_entry *)baseentry;
  310         return ((entry->ent.dp_typ == DOSPTYP_386BSD) ? 1 : 0);
  311 }
  312 
  313 #if defined(GEOM_PART_EBR_COMPAT)
  314 static void
  315 g_part_ebr_fullname(struct g_part_table *table, struct g_part_entry *entry,
  316     struct sbuf *sb, const char *pfx)
  317 {
  318         struct g_part_entry *iter;
  319         u_int idx;
  320 
  321         idx = 5;
  322         LIST_FOREACH(iter, &table->gpt_entry, gpe_entry) {
  323                 if (iter == entry)
  324                         break;
  325                 idx++;
  326         }
  327         sbuf_printf(sb, "%.*s%u", (int)strlen(pfx) - 1, pfx, idx);
  328 }
  329 #endif
  330 
  331 static int
  332 g_part_ebr_modify(struct g_part_table *basetable,
  333     struct g_part_entry *baseentry, struct g_part_parms *gpp)
  334 {
  335         struct g_part_ebr_entry *entry;
  336 
  337         if (gpp->gpp_parms & G_PART_PARM_LABEL)
  338                 return (EINVAL);
  339 
  340         entry = (struct g_part_ebr_entry *)baseentry;
  341         if (gpp->gpp_parms & G_PART_PARM_TYPE)
  342                 return (ebr_parse_type(gpp->gpp_type, &entry->ent.dp_typ));
  343         return (0);
  344 }
  345 
  346 static const char *
  347 g_part_ebr_name(struct g_part_table *table, struct g_part_entry *entry,
  348     char *buf, size_t bufsz)
  349 {
  350 
  351         snprintf(buf, bufsz, "+%08u", entry->gpe_index);
  352         return (buf);
  353 }
  354 
  355 static int
  356 g_part_ebr_precheck(struct g_part_table *table, enum g_part_ctl req,
  357     struct g_part_parms *gpp)
  358 {
  359 #if defined(GEOM_PART_EBR_COMPAT)
  360         return (ECANCELED);
  361 #else
  362         /*
  363          * The index is a function of the start of the partition.
  364          * This is not something the user can override, nor is it
  365          * something the common code will do right. We can set the
  366          * index now so that we get what we need.
  367          */
  368         if (req == G_PART_CTL_ADD)
  369                 gpp->gpp_index = (gpp->gpp_start / table->gpt_sectors) + 1;
  370         return (0);
  371 #endif
  372 }
  373 
  374 static int
  375 g_part_ebr_probe(struct g_part_table *table, struct g_consumer *cp)
  376 {
  377         char psn[8];
  378         struct g_provider *pp;
  379         u_char *buf, *p;
  380         int error, index, res, sum;
  381         uint16_t magic;
  382 
  383         pp = cp->provider;
  384 
  385         /* Sanity-check the provider. */
  386         if (pp->sectorsize < EBRSIZE || pp->mediasize < pp->sectorsize)
  387                 return (ENOSPC);
  388         if (pp->sectorsize > 4096)
  389                 return (ENXIO);
  390 
  391         /* Check that we have a parent and that it's a MBR. */
  392         if (table->gpt_depth == 0)
  393                 return (ENXIO);
  394         error = g_getattr("PART::scheme", cp, &psn);
  395         if (error)
  396                 return (error);
  397         if (strcmp(psn, "MBR"))
  398                 return (ENXIO);
  399 
  400         /* Check that there's a EBR. */
  401         buf = g_read_data(cp, 0L, pp->sectorsize, &error);
  402         if (buf == NULL)
  403                 return (error);
  404 
  405         /* We goto out on mismatch. */
  406         res = ENXIO;
  407 
  408         magic = le16dec(buf + DOSMAGICOFFSET);
  409         if (magic != DOSMAGIC)
  410                 goto out;
  411 
  412         /*
  413          * The sector is all zeroes, except for the partition entries
  414          * and some signatures or disk serial number. Those can be
  415          * found in the 9 bytes immediately in front of the partition
  416          * table.
  417          */
  418         sum = 0;
  419         for (index = 0; index < DOSPARTOFF - 9; index++)
  420                 sum += buf[index];
  421         if (sum != 0)
  422                 goto out;
  423 
  424         for (index = 0; index < NDOSPART; index++) {
  425                 p = buf + DOSPARTOFF + index * DOSPARTSIZE;
  426                 if (p[0] != 0 && p[0] != 0x80)
  427                         goto out;
  428                 if (index < 2)
  429                         continue;
  430                 /* The 3rd & 4th entries are always zero. */
  431                 if ((le64dec(p+0) + le64dec(p+8)) != 0)
  432                         goto out;
  433         }
  434 
  435         res = G_PART_PROBE_PRI_NORM;
  436 
  437  out:
  438         g_free(buf);
  439         return (res);
  440 }
  441 
  442 static int
  443 g_part_ebr_read(struct g_part_table *basetable, struct g_consumer *cp)
  444 {
  445         struct dos_partition ent[2];
  446         struct g_provider *pp;
  447         struct g_part_entry *baseentry;
  448         struct g_part_ebr_table *table;
  449         struct g_part_ebr_entry *entry;
  450         u_char *buf;
  451         off_t ofs, msize;
  452         u_int lba;
  453         int error, index;
  454 
  455         pp = cp->provider;
  456         table = (struct g_part_ebr_table *)basetable;
  457         msize = pp->mediasize / pp->sectorsize;
  458 
  459         lba = 0;
  460         while (1) {
  461                 ofs = (off_t)lba * pp->sectorsize;
  462                 buf = g_read_data(cp, ofs, pp->sectorsize, &error);
  463                 if (buf == NULL)
  464                         return (error);
  465 
  466                 ebr_entry_decode(buf + DOSPARTOFF + 0 * DOSPARTSIZE, ent + 0);
  467                 ebr_entry_decode(buf + DOSPARTOFF + 1 * DOSPARTSIZE, ent + 1);
  468                 g_free(buf);
  469 
  470                 if (ent[0].dp_typ == 0)
  471                         break;
  472 
  473                 if (ent[0].dp_typ == 5 && ent[1].dp_typ == 0) {
  474                         lba = ent[0].dp_start;
  475                         continue;
  476                 }
  477 
  478                 index = (lba / basetable->gpt_sectors) + 1;
  479                 baseentry = (struct g_part_entry *)g_part_new_entry(basetable,
  480                     index, lba, lba + ent[0].dp_start + ent[0].dp_size - 1);
  481                 baseentry->gpe_offset = (off_t)(lba + ent[0].dp_start) *
  482                     pp->sectorsize;
  483                 entry = (struct g_part_ebr_entry *)baseentry;
  484                 entry->ent = ent[0];
  485 
  486                 if (ent[1].dp_typ == 0)
  487                         break;
  488 
  489                 lba = ent[1].dp_start;
  490         }
  491 
  492         basetable->gpt_entries = msize / basetable->gpt_sectors;
  493         basetable->gpt_first = 0;
  494         basetable->gpt_last = msize - (msize % basetable->gpt_sectors) - 1;
  495         return (0);
  496 }
  497 
  498 static int
  499 g_part_ebr_setunset(struct g_part_table *table, struct g_part_entry *baseentry,
  500     const char *attrib, unsigned int set)
  501 {
  502         struct g_part_entry *iter;
  503         struct g_part_ebr_entry *entry;
  504         int changed;
  505 
  506         if (strcasecmp(attrib, "active") != 0)
  507                 return (EINVAL);
  508 
  509         /* Only one entry can have the active attribute. */
  510         LIST_FOREACH(iter, &table->gpt_entry, gpe_entry) {
  511                 if (iter->gpe_deleted)
  512                         continue;
  513                 changed = 0;
  514                 entry = (struct g_part_ebr_entry *)iter;
  515                 if (iter == baseentry) {
  516                         if (set && (entry->ent.dp_flag & 0x80) == 0) {
  517                                 entry->ent.dp_flag |= 0x80;
  518                                 changed = 1;
  519                         } else if (!set && (entry->ent.dp_flag & 0x80)) {
  520                                 entry->ent.dp_flag &= ~0x80;
  521                                 changed = 1;
  522                         }
  523                 } else {
  524                         if (set && (entry->ent.dp_flag & 0x80)) {
  525                                 entry->ent.dp_flag &= ~0x80;
  526                                 changed = 1;
  527                         }
  528                 }
  529                 if (changed && !iter->gpe_created)
  530                         iter->gpe_modified = 1;
  531         }
  532         return (0);
  533 }
  534 
  535 static const char *
  536 g_part_ebr_type(struct g_part_table *basetable, struct g_part_entry *baseentry, 
  537     char *buf, size_t bufsz)
  538 {
  539         struct g_part_ebr_entry *entry;
  540         int type;
  541 
  542         entry = (struct g_part_ebr_entry *)baseentry;
  543         type = entry->ent.dp_typ;
  544         if (type == DOSPTYP_386BSD)
  545                 return (g_part_alias_name(G_PART_ALIAS_FREEBSD));
  546         snprintf(buf, bufsz, "!%d", type);
  547         return (buf);
  548 }
  549 
  550 static int
  551 g_part_ebr_write(struct g_part_table *basetable, struct g_consumer *cp)
  552 {
  553         struct g_provider *pp;
  554         struct g_part_entry *baseentry, *next;
  555         struct g_part_ebr_entry *entry;
  556         u_char *buf;
  557         u_char *p;
  558         int error;
  559 
  560         pp = cp->provider;
  561         buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO);
  562         le16enc(buf + DOSMAGICOFFSET, DOSMAGIC);
  563 
  564         baseentry = LIST_FIRST(&basetable->gpt_entry);
  565         while (baseentry != NULL && baseentry->gpe_deleted)
  566                 baseentry = LIST_NEXT(baseentry, gpe_entry);
  567 
  568         /* Wipe-out the the first EBR when there are no slices. */
  569         if (baseentry == NULL) {
  570                 error = g_write_data(cp, 0, buf, pp->sectorsize);
  571                 goto out;
  572         }
  573 
  574         /*
  575          * If the first partition is not in LBA 0, we need to
  576          * put a "link" EBR in LBA 0.
  577          */
  578         if (baseentry->gpe_start != 0) {
  579                 ebr_entry_link(basetable, (uint32_t)baseentry->gpe_start,
  580                     (uint32_t)baseentry->gpe_end, buf + DOSPARTOFF);
  581                 error = g_write_data(cp, 0, buf, pp->sectorsize);
  582                 if (error)
  583                         goto out;
  584         }
  585 
  586         do {
  587                 entry = (struct g_part_ebr_entry *)baseentry;
  588 
  589                 p = buf + DOSPARTOFF;
  590                 p[0] = entry->ent.dp_flag;
  591                 p[1] = entry->ent.dp_shd;
  592                 p[2] = entry->ent.dp_ssect;
  593                 p[3] = entry->ent.dp_scyl;
  594                 p[4] = entry->ent.dp_typ;
  595                 p[5] = entry->ent.dp_ehd;
  596                 p[6] = entry->ent.dp_esect;
  597                 p[7] = entry->ent.dp_ecyl;
  598                 le32enc(p + 8, entry->ent.dp_start);
  599                 le32enc(p + 12, entry->ent.dp_size);
  600  
  601                 next = LIST_NEXT(baseentry, gpe_entry);
  602                 while (next != NULL && next->gpe_deleted)
  603                         next = LIST_NEXT(next, gpe_entry);
  604 
  605                 p += DOSPARTSIZE;
  606                 if (next != NULL)
  607                         ebr_entry_link(basetable, (uint32_t)next->gpe_start,
  608                             (uint32_t)next->gpe_end, p);
  609                 else
  610                         bzero(p, DOSPARTSIZE);
  611 
  612                 error = g_write_data(cp, baseentry->gpe_start * pp->sectorsize,
  613                     buf, pp->sectorsize);
  614 
  615                 baseentry = next;
  616         } while (!error && baseentry != NULL);
  617 
  618  out:
  619         g_free(buf);
  620         return (error);
  621 }

Cache object: 2817a9f41dfd27d82768aebcdab8981a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.