1 /* $NetBSD: disklabel_conv.c,v 1.4 2008/04/28 20:23:18 martin Exp $ */
2
3 /*-
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by UCHIYAMA Yasushi.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: disklabel_conv.c,v 1.4 2008/04/28 20:23:18 martin Exp $");
34
35 #include <sys/systm.h>
36 #include <sys/param.h>
37
38 #ifndef _KERNEL
39 #include "local.h"
40 #endif
41
42 #include <sys/disklabel.h>
43
44 /*
45 * NetBSD/ews4800mips EWS-UX compatible disk layout.
46 *
47 * 0============================+ cylinder 0
48 * 1 1stboot program (4KB) |
49 * . .
50 * 7----------------------------+
51 * 8 PDINFO | UX unvisible region.
52 * 9 BSD disklabel | I (uch) decided to locate disklabel here.
53 * . .
54 * . error log (UX) |
55 * +============================+ cylinder 1
56 * | logical_start (UX) |
57 * | VTOC |
58 * . . UX Boot block (partition 7)
59 * . . 100 blocks (default. at least 2 blocks)
60 * . .
61 * . .
62 * +============================+
63 * | BFS |
64 * | boot loader |
65 * . disklabel .
66 * . and etc. . BFS (partition 3)
67 * . .
68 * . .
69 * . .
70 * -----------------------------+
71 */
72
73 #define _BFS_SIZE 16384 /* 8MB */
74 #define _BOOTBLOCK_SIZE 100 /* UX default */
75 #define _FAKE_TRACKS_PER_CYLINDER 16
76 #define _FAKE_SECTORS_PER_TRACK 1
77
78 void
disklabel_set_default(struct disklabel * d)79 disklabel_set_default(struct disklabel *d)
80 {
81
82 d->d_magic = DISKMAGIC;
83 d->d_magic2 = DISKMAGIC;
84 d->d_secsize = DEV_BSIZE;
85 d->d_npartitions = MAXPARTITIONS;
86 }
87
88 void
vtoc_set_default(struct cpu_disklabel * ux,struct disklabel * d)89 vtoc_set_default( struct cpu_disklabel *ux, struct disklabel *d)
90 {
91 struct pdinfo_sector *pdinfo = &ux->pdinfo;
92 struct vtoc_sector *vtoc = &ux->vtoc;
93 struct ux_partition *bfs;
94 struct ux_partition *boot;
95 struct ux_partition *bsdraw;
96 int nsectors, logical_sector, cylinder_blocks, res;
97
98 memset(vtoc, 0, sizeof *vtoc);
99 memset(pdinfo, 0, sizeof *pdinfo);
100 if (d)
101 cylinder_blocks = d->d_ntracks * d->d_nsectors;
102 else
103 cylinder_blocks =
104 _FAKE_TRACKS_PER_CYLINDER * _FAKE_SECTORS_PER_TRACK;
105 logical_sector = cylinder_blocks;
106
107 pdinfo->drive_id = 0x5c512000; /* Fake for EWS-UX */
108 pdinfo->magic = PDINFO_MAGIC;
109 pdinfo->version = PDINFO_VERSION;
110 pdinfo->logical_sector = logical_sector;
111 pdinfo->ux.errorlog_sector = logical_sector - 1;
112 pdinfo->ux.errorlog_size_byte = DEV_BSIZE;
113
114 if (d) { /* use drivers disk geometory */
115 pdinfo->geometory.cylinders_per_drive = d->d_ncylinders;
116 pdinfo->geometory.tracks_per_cylinder = d->d_ntracks;
117 pdinfo->geometory.sectors_per_track = d->d_nsectors;
118 pdinfo->geometory.bytes_per_sector = d->d_secsize;
119 nsectors = d->d_ncylinders * d->d_ntracks * d->d_nsectors;
120 } else { /* set fake */
121 pdinfo->geometory.sectors_per_track =
122 _FAKE_SECTORS_PER_TRACK;
123 pdinfo->geometory.tracks_per_cylinder =
124 _FAKE_TRACKS_PER_CYLINDER;
125 pdinfo->geometory.cylinders_per_drive = 0x1fffffff;
126 pdinfo->geometory.bytes_per_sector = DEV_BSIZE;
127 nsectors = 0x1fffffff;
128 }
129
130 /* following magic numbers are required for EWS-UX */
131 pdinfo->device_depend[15] = 0xfb7e10;
132 pdinfo->device_depend[16] = 0x200;
133 pdinfo->device_depend[17] = 0x10;
134
135 vtoc->magic = VTOC_MAGIC;
136 vtoc->version = VTOC_VERSION;
137 vtoc->sector_size_byte = DEV_BSIZE;
138 vtoc->npartitions = VTOC_MAXPARTITIONS;
139
140 boot = &vtoc->partition[7];
141 boot->tag = VTOC_TAG_BOOT;
142 boot->flags = VTOC_FLAG_UNMOUNT;
143 boot->start_sector = 0;
144 boot->nsectors = _BOOTBLOCK_SIZE;
145
146 bfs = &vtoc->partition[3];
147 bfs->tag = VTOC_TAG_STAND;
148 bfs->flags = 0;
149 bfs->start_sector = _BOOTBLOCK_SIZE;
150
151 res = nsectors - bfs->start_sector;
152 bfs->nsectors = res > _BFS_SIZE ? _BFS_SIZE : res;
153
154 bsdraw = &vtoc->partition[RAW_PART];
155 bsdraw->tag = VTOC_TAG_NONAME;
156 bsdraw->flags = VTOC_FLAG_UNMOUNT;
157 bsdraw->start_sector = -pdinfo->logical_sector;
158 bsdraw->nsectors = nsectors;
159 }
160
161 void
disklabel_to_vtoc(struct cpu_disklabel * ux,struct disklabel * d)162 disklabel_to_vtoc(struct cpu_disklabel *ux, struct disklabel *d)
163 {
164 struct pdinfo_sector *pdinfo = &ux->pdinfo;
165 struct vtoc_sector *vtoc = &ux->vtoc;
166 struct ux_partition *up;
167 struct partition *p;
168 uint32_t offset = pdinfo->logical_sector;
169 int i;
170
171 pdinfo->geometory.cylinders_per_drive = d->d_ncylinders;
172 pdinfo->geometory.tracks_per_cylinder = d->d_ntracks;
173 pdinfo->geometory.sectors_per_track = d->d_nsectors;
174 pdinfo->geometory.bytes_per_sector = d->d_secsize;
175
176 vtoc->npartitions = d->d_npartitions;
177 vtoc->sector_size_byte = d->d_secsize;
178
179 up = vtoc->partition;
180 p = d->d_partitions;
181 for (i = 0; i < vtoc->npartitions; i++, up++, p++) {
182 if ((up->nsectors = p->p_size) != 0)
183 up->start_sector = p->p_offset - offset;
184 else
185 up->start_sector = 0;
186
187 switch (p->p_fstype) {
188 case FS_BOOT:
189 up->tag = VTOC_TAG_BOOT;
190 up->flags = VTOC_FLAG_UNMOUNT;
191 break;
192 case FS_SYSVBFS:
193 up->tag = VTOC_TAG_STAND;
194 break;
195 case FS_SWAP:
196 up->tag = VTOC_TAG_SWAP;
197 up->flags = VTOC_FLAG_UNMOUNT;
198 break;
199 case FS_BSDFFS:
200 up->tag = __VTOC_TAG_BSDFFS;
201 break;
202 case FS_UNUSED:
203 if (i != RAW_PART && p->p_size > 0) {
204 up->tag = VTOC_TAG_RAWDISK;
205 up->flags = VTOC_FLAG_UNMOUNT;
206 }
207 break;
208 default:
209 break;
210 }
211 }
212 }
213
214 void
vtoc_to_disklabel(struct cpu_disklabel * ux,struct disklabel * d)215 vtoc_to_disklabel(struct cpu_disklabel *ux, struct disklabel *d)
216 {
217 struct pdinfo_sector *pdinfo = &ux->pdinfo;
218 struct vtoc_sector *vtoc = &ux->vtoc;
219 struct ux_partition *up;
220 struct partition *p;
221 uint32_t offset = pdinfo->logical_sector;
222 int i;
223
224 d->d_secsize = pdinfo->geometory.bytes_per_sector;
225 d->d_nsectors = pdinfo->geometory.sectors_per_track;
226 d->d_ntracks = pdinfo->geometory.tracks_per_cylinder;
227 d->d_ncylinders = pdinfo->geometory.cylinders_per_drive;
228 d->d_secpercyl = d->d_nsectors * d->d_ntracks;
229 d->d_secperunit = d->d_ncylinders * d->d_secpercyl;
230
231 d->d_npartitions = vtoc->npartitions;
232 d->d_secsize = vtoc->sector_size_byte;
233
234 up = vtoc->partition;
235 p = d->d_partitions;
236 for (i = 0; i < vtoc->npartitions; i++, up++, p++) {
237
238 if ((p->p_size = up->nsectors) != 0)
239 p->p_offset = up->start_sector + offset;
240 else
241 p->p_offset = 0;
242
243 switch (up->tag) {
244 case VTOC_TAG_BOOT:
245 p->p_fstype = FS_BOOT;
246 break;
247 case VTOC_TAG_STAND:
248 p->p_fstype = FS_SYSVBFS;
249 break;
250 case VTOC_TAG_RAWDISK:
251 p->p_fstype = FS_UNUSED;
252 break;
253 case VTOC_TAG_SWAP:
254 p->p_fstype = FS_SWAP;
255 break;
256 case VTOC_TAG_NONAME:
257 case VTOC_TAG_ROOT:
258 case VTOC_TAG_USR:
259 case VTOC_TAG_VAR:
260 case VTOC_TAG_HOME:
261 p->p_fstype = FS_SYSV;
262 break;
263 default:
264 if (up->nsectors != 0)
265 p->p_fstype = FS_SYSV;
266 else
267 p->p_fstype = FS_UNUSED;
268 break;
269 }
270 }
271
272 d->d_checksum = 0;
273 d->d_checksum = dkcksum(d);
274 }
275
276 bool
disklabel_sanity(struct disklabel * d)277 disklabel_sanity(struct disklabel *d)
278 {
279
280 if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC ||
281 dkcksum(d) != 0)
282 return false;
283
284 return true;
285 }
286