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 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 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 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 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 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