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 }