1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * libparted - a library for manipulating disk partitions
  28  *
  29  * This module recognizes the Solaris x86 VTOC so that the
  30  * partition can be identified as "solaris".
  31  *
  32  * Mark Logan <mark.logan@sun.com>
  33  */
  34 
  35 #include <config.h>
  36 
  37 #include <parted/parted.h>
  38 #include <parted/endian.h>
  39 #include <parted/debug.h>
  40 
  41 #if ENABLE_NLS
  42 #include <libintl.h>
  43 #define _(String)       dgettext(PACKAGE, String)
  44 #else
  45 #define _(String)       (String)
  46 #endif /* ENABLE_NLS */
  47 
  48 #include <unistd.h>
  49 #include <string.h>
  50 
  51 #define BLOCK_SIZES     ((int[2]) {512, 0})
  52 
  53 #define VTOC_SANE       0x600DDEEE
  54 #define LEN_DKL_VVOL    8
  55 #define V_NUMPAR        16              /* # of logical partitions */
  56 #define LEN_DKL_ASCII   128             /* length of dkl_asciilabel */
  57 
  58 #define LEN_DKL_PAD     \
  59         (512 - \
  60         ((5 * sizeof (uint32_t)) + \
  61         LEN_DKL_VVOL + \
  62         (2 * sizeof (uint16_t)) + \
  63         (10 * sizeof (uint32_t)) + \
  64         (V_NUMPAR * sizeof (struct partition)) + \
  65         (V_NUMPAR * sizeof (uint32_t)) + \
  66         LEN_DKL_ASCII + \
  67         (2 * (sizeof (uint16_t)))))
  68 
  69 #define DKL_MAGIC       0xDABE          /* magic number */
  70 
  71 struct partition {
  72         unsigned short p_tag;           /* ID tag of partition */
  73         unsigned short p_flag;          /* permission flags */
  74         long p_start;                   /* start sector no of partition */
  75         long p_size;                    /* # of blocks in partition */
  76 };
  77 
  78 struct vtoc {
  79         unsigned long   v_bootinfo[3];  /* info for mboot (unsupported) */
  80         unsigned long   v_sanity;       /* to verify vtoc sanity */
  81         unsigned long   v_version;      /* layout version */
  82         char            v_volume[LEN_DKL_VVOL]; /* volume name */
  83         unsigned short  v_sectorsz;     /* sector size in bytes */
  84         unsigned short  v_nparts;       /* number of partitions */
  85         unsigned long   v_reserved[10]; /* free space */
  86         struct partition v_part[V_NUMPAR]; /* partition headers */
  87         int32_t timestamp[V_NUMPAR];    /* partition timestamp (unsupported) */
  88         char             v_asciilabel[LEN_DKL_ASCII];   /* for compatibility */
  89         char            dkl_pad[LEN_DKL_PAD];   /* unused part of 512 bytes */
  90         uint16_t        dkl_magic;      /* identifies this label format */
  91         uint16_t        dkl_cksum;      /* xor checksum of sector */
  92 };
  93 
  94 static PedGeometry*
  95 solaris_x86_probe(PedGeometry* geom)
  96 {
  97         int8_t buf[512 * 3];
  98         struct vtoc *pvtoc;
  99         uint16_t *dkl_magic;
 100 
 101         if (geom->length < 5)
 102                 return (0);
 103         if (!ped_geometry_read(geom, buf, 1, 1))
 104                 return (0);
 105 
 106         pvtoc = (struct vtoc *)buf;
 107 
 108         if (pvtoc->v_sanity == VTOC_SANE && pvtoc->dkl_magic == DKL_MAGIC) {
 109                 PedSector block_size = pvtoc->v_sectorsz / 512;
 110                 /*
 111                  * Use the size of the backup slice:
 112                  */
 113                 PedSector block_count = pvtoc->v_part[2].p_size;
 114                 return ped_geometry_new(geom->dev, geom->start,
 115                     block_size * block_count);
 116         }
 117 
 118         return (NULL);
 119 }
 120 
 121 #ifndef DISCOVER_ONLY
 122 static int
 123 solaris_x86_clobber(PedGeometry* geom)
 124 {
 125         char    buf[512*3];
 126 
 127         if (!ped_geometry_read(geom, buf, 1, 1))
 128                 return (0);
 129 
 130         memset(buf, 0, sizeof (struct vtoc));
 131 
 132         return (ped_geometry_write(geom, buf, 1, 1));
 133 }
 134 #endif /* !DISCOVER_ONLY */
 135 
 136 static PedFileSystemOps solaris_x86_ops = {
 137         .probe = solaris_x86_probe,
 138 #ifndef DISCOVER_ONLY
 139         .clobber = solaris_x86_clobber,
 140 #else
 141         .clobber = NULL,
 142 #endif
 143         .open = NULL,
 144         .create = NULL,
 145         .close = NULL,
 146         .check = NULL,
 147         .copy =  NULL,
 148         .resize = NULL,
 149         .get_create_constraint = NULL,
 150         .get_resize_constraint = NULL,
 151         .get_copy_constraint = NULL
 152 };
 153 
 154 static PedFileSystemType solaris_x86_type = {
 155         .next = NULL,
 156         .ops =  &solaris_x86_ops,
 157         .name = "solaris",
 158         .block_sizes = BLOCK_SIZES
 159 };
 160 
 161 void
 162 ped_file_system_solaris_x86_init()
 163 {
 164         ped_file_system_type_register(&solaris_x86_type);
 165 }
 166 
 167 void
 168 ped_file_system_solaris_x86_done()
 169 {
 170         ped_file_system_type_unregister(&solaris_x86_type);
 171 }