1 1.9 snj /* $NetBSD: chg_pid.c,v 1.9 2009/10/20 19:10:11 snj Exp $ */ 2 1.1 leo 3 1.1 leo /* 4 1.1 leo * Copyright (c) 1995 L. Weppelman 5 1.1 leo * All rights reserved. 6 1.1 leo * 7 1.1 leo * Redistribution and use in source and binary forms, with or without 8 1.1 leo * modification, are permitted provided that the following conditions 9 1.1 leo * are met: 10 1.1 leo * 1. Redistributions of source code must retain the above copyright 11 1.1 leo * notice, this list of conditions and the following disclaimer. 12 1.1 leo * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 leo * notice, this list of conditions and the following disclaimer in the 14 1.1 leo * documentation and/or other materials provided with the distribution. 15 1.1 leo * 16 1.1 leo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 leo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 leo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 leo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 leo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.1 leo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.1 leo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.1 leo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.1 leo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 1.1 leo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.1 leo */ 27 1.1 leo 28 1.1 leo /* 29 1.1 leo * 30 1.1 leo * This program changes the partition id field (p_id) in the GEM 31 1.1 leo * partition info. NetBSD uses these id-fields to determine the kind 32 1.1 leo * of partition. Sensible id's to set are: 33 1.1 leo * NBU : NetBSD User partition 34 1.1 leo * NBR : NetBSD Root partition 35 1.1 leo * NBS : NetBSD Swap partition 36 1.2 leo * NBD : General NetBSD partition 37 1.2 leo * RAW : Partition hidden for GEMDOS 38 1.1 leo * 39 1.1 leo * When NetBSD auto boots, the first 'NBR' partition found when scanning the 40 1.1 leo * SCSI-disks becomes the active root partition. The same goes for 'NBS'. 41 1.1 leo * Drives are scanned in 'SCSI-id' order. 42 1.1 leo */ 43 1.2 leo #include <sys/types.h> 44 1.2 leo #include <osbind.h> 45 1.2 leo #include <stdlib.h> 46 1.2 leo #include <string.h> 47 1.2 leo #include <unistd.h> 48 1.1 leo #include <stdio.h> 49 1.2 leo #include "libtos.h" 50 1.2 leo 51 1.2 leo #ifndef Dmawrite 52 1.2 leo #define Dmawrite DMAwrite 53 1.2 leo #endif 54 1.2 leo #ifndef Dmaread 55 1.2 leo #define Dmaread DMAread 56 1.2 leo #endif 57 1.1 leo 58 1.1 leo /* 59 1.1 leo * Format of GEM root sector 60 1.1 leo */ 61 1.1 leo typedef struct gem_part { 62 1.1 leo u_char p_flg; /* bit 0 is in-use flag */ 63 1.2 leo char p_id[3]; /* id: GEM, BGM, XGM, UNX, MIX */ 64 1.1 leo u_long p_st; /* block where partition starts */ 65 1.1 leo u_long p_size; /* partition size */ 66 1.1 leo } GEM_PART; 67 1.1 leo 68 1.2 leo /* 69 1.2 leo * Defines for p_flg 70 1.2 leo */ 71 1.2 leo #define P_VALID 0x01 /* info is valid */ 72 1.2 leo #define P_ACTIVE 0x80 /* partition is active */ 73 1.2 leo 74 1.1 leo #define NGEM_PARTS 4 /* Max. partition infos in root sector */ 75 1.1 leo 76 1.1 leo typedef struct gem_root { 77 1.1 leo u_char fill[0x1c2]; /* Filler, can be boot code */ 78 1.1 leo u_long hd_siz; /* size of entire volume */ 79 1.1 leo GEM_PART parts[NGEM_PARTS]; /* see above */ 80 1.1 leo u_long bsl_st; /* start of bad-sector list */ 81 1.1 leo u_long bsl_cnt; /* nr. blocks in bad-sector list*/ 82 1.1 leo u_short csum; /* checksum correction */ 83 1.1 leo } GEM_ROOT; 84 1.1 leo 85 1.2 leo void help PROTO((void)); 86 1.2 leo void usage PROTO((void)); 87 1.2 leo int chg_tosparts PROTO((int, int, char *)); 88 1.2 leo void change_it PROTO((int, GEM_PART *, char *)); 89 1.2 leo int read_block PROTO((void *, int, int)); 90 1.2 leo int write_block PROTO((void *, int, int)); 91 1.2 leo void set_csum PROTO((char *)); 92 1.2 leo 93 1.9 snj const char version[] = "$Revision: 1.9 $"; 94 1.2 leo 95 1.2 leo char *Progname = NULL; /* What are we called */ 96 1.2 leo int t_flag = 0; /* Test -- don't actually do it */ 97 1.2 leo int v_flag = 0; /* show version */ 98 1.2 leo int h_flag = 0; /* show help */ 99 1.2 leo 100 1.2 leo int 101 1.5 dsl main(int argc, char *argv[]) 102 1.1 leo { 103 1.2 leo /* 104 1.2 leo * Option parsing 105 1.2 leo */ 106 1.2 leo extern int optind; 107 1.2 leo extern char *optarg; 108 1.2 leo 109 1.2 leo int driveno = 0; 110 1.2 leo int partno = 0; 111 1.2 leo char *newname = NULL; 112 1.1 leo int c; 113 1.1 leo 114 1.2 leo init_toslib(argv[0]); 115 1.2 leo Progname = argv[0]; 116 1.2 leo 117 1.4 lukem while ((c = getopt(argc, argv, "htVwo:")) != -1) { 118 1.2 leo switch (c) { 119 1.2 leo case 'h': 120 1.2 leo h_flag = 1; 121 1.2 leo break; 122 1.2 leo case 'o': 123 1.2 leo redirect_output(optarg); 124 1.2 leo break; 125 1.2 leo case 't': 126 1.2 leo t_flag = 1; 127 1.2 leo break; 128 1.2 leo case 'V': 129 1.2 leo v_flag = 1; 130 1.2 leo break; 131 1.2 leo case 'w': 132 1.2 leo set_wait_for_key(); 133 1.2 leo break; 134 1.2 leo default: 135 1.2 leo usage(); 136 1.2 leo } 137 1.2 leo } 138 1.2 leo argc -= optind; 139 1.2 leo argv += optind; 140 1.2 leo 141 1.2 leo if (h_flag) 142 1.2 leo help(); 143 1.2 leo 144 1.2 leo if (v_flag) { 145 1.2 leo eprintf("%s\r\n", version); 146 1.2 leo if (argc != 3) 147 1.2 leo xexit(0); 148 1.2 leo } 149 1.2 leo 150 1.2 leo if (argc != 3) 151 1.1 leo usage(); 152 1.2 leo 153 1.2 leo eprintf("Note: >>> Both drive and partition numbers start " 154 1.2 leo "at 0! <<<\r\n"); 155 1.2 leo 156 1.2 leo driveno = atoi(argv[0]); 157 1.2 leo partno = atoi(argv[1]); 158 1.2 leo newname = argv[2]; 159 1.2 leo eprintf("About to change id of partition %d on drive %d to %s\r\n", 160 1.2 leo partno, driveno, newname); 161 1.2 leo 162 1.2 leo if (!t_flag) 163 1.2 leo c = key_wait("Are you sure (y/n)? "); 164 1.2 leo else c = 'y'; 165 1.1 leo switch(c) { 166 1.1 leo case 'y': 167 1.1 leo case 'Y': 168 1.2 leo if(chg_tosparts(partno, driveno, newname)) { 169 1.2 leo if (!t_flag) 170 1.2 leo eprintf("Done\r\n"); 171 1.2 leo else eprintf("Not Done\r\n"); 172 1.2 leo xexit(0); 173 1.2 leo } 174 1.2 leo else eprintf("Partition number not found\r\n"); 175 1.1 leo break; 176 1.1 leo default : 177 1.2 leo eprintf("Aborted\r\n"); 178 1.2 leo xexit(1); 179 1.2 leo break; 180 1.1 leo } 181 1.2 leo xexit(0); 182 1.1 leo } 183 1.1 leo 184 1.1 leo int chg_tosparts(chg_part, drive, newname) 185 1.1 leo int chg_part, drive; 186 1.1 leo char *newname; 187 1.1 leo { 188 1.2 leo GEM_ROOT *g_root; 189 1.2 leo GEM_PART g_local[NGEM_PARTS]; 190 1.2 leo char buf[512]; 191 1.2 leo int pno = 0; 192 1.2 leo int i; 193 1.2 leo 194 1.2 leo /* 195 1.2 leo * Read root sector 196 1.2 leo */ 197 1.2 leo if (read_block(buf, 0, drive) == 0) 198 1.2 leo fatal(-1, "Cannot read block 0\r\n"); 199 1.2 leo 200 1.2 leo /* 201 1.2 leo * Make local copy of partition info, we may need to re-use 202 1.2 leo * the buffer in case of 'XGM' partitions. 203 1.2 leo */ 204 1.2 leo g_root = (GEM_ROOT*)buf; 205 1.8 tsutsui memcpy(g_local, g_root->parts, NGEM_PARTS*sizeof(GEM_PART)); 206 1.2 leo 207 1.2 leo for (i = 0; i < NGEM_PARTS; i++) { 208 1.2 leo if (!(g_local[i].p_flg & 1)) 209 1.2 leo continue; 210 1.2 leo if (!strncmp(g_local[i].p_id, "XGM", 3)) { 211 1.2 leo int j; 212 1.2 leo daddr_t new_root = g_local[i].p_st; 213 1.2 leo 214 1.2 leo /* 215 1.2 leo * Loop through extended partition list 216 1.2 leo */ 217 1.2 leo for(;;) { 218 1.2 leo if (read_block(buf, new_root, drive) == 0) 219 1.2 leo fatal(-1, "Cannot read block %d\r\n", new_root); 220 1.2 leo for (j = 0; j < NGEM_PARTS; j++) { 221 1.2 leo if (!(g_root->parts[j].p_flg & 1)) 222 1.2 leo continue; 223 1.2 leo if (!strncmp(g_root->parts[j].p_id, "XGM", 3)) { 224 1.2 leo new_root = g_local[i].p_st + g_root->parts[j].p_st; 225 1.2 leo break; 226 1.1 leo } 227 1.2 leo else { 228 1.2 leo if (pno == chg_part) { 229 1.2 leo change_it(pno, &g_root->parts[j], newname); 230 1.2 leo if (t_flag) 231 1.1 leo return(1); 232 1.2 leo if (write_block(buf, new_root, drive) == 0) 233 1.2 leo fatal(-1, "Cannot write block %d\r\n",new_root); 234 1.2 leo return(1); 235 1.1 leo } 236 1.2 leo pno++; 237 1.1 leo } 238 1.1 leo } 239 1.2 leo if (j == NGEM_PARTS) 240 1.2 leo break; 241 1.1 leo } 242 1.2 leo } 243 1.2 leo else { 244 1.2 leo if (pno == chg_part) { 245 1.2 leo /* 246 1.2 leo * Re-read block 0 247 1.2 leo */ 248 1.2 leo if (read_block(buf, 0, drive) == 0) 249 1.2 leo fatal(-1, "Cannot read block 0\r\n"); 250 1.2 leo change_it(pno, &g_root->parts[i], newname); 251 1.2 leo if (t_flag) 252 1.2 leo return(1); 253 1.2 leo set_csum(buf); 254 1.2 leo if (write_block(buf, 0, drive) == 0) 255 1.2 leo fatal(-1, "Cannot write block 0\r\n"); 256 1.2 leo return(1); 257 1.1 leo } 258 1.2 leo pno++; 259 1.1 leo } 260 1.2 leo } 261 1.2 leo return(0); 262 1.1 leo } 263 1.1 leo 264 1.2 leo void change_it(pno, gp, newname) 265 1.2 leo int pno; 266 1.2 leo GEM_PART *gp; 267 1.2 leo char *newname; 268 1.1 leo { 269 1.1 leo char s1[4], s2[4]; 270 1.1 leo 271 1.2 leo strncpy(s1, gp->p_id, 3); 272 1.1 leo strncpy(s2, newname, 3); 273 1.1 leo s1[3] = s2[3] = '\0'; 274 1.2 leo eprintf("Changing partition %d: %s -> %s ...", pno, s1, s2); 275 1.2 leo gp->p_id[0] = s2[0]; gp->p_id[1] = s2[1]; gp->p_id[2] = s2[2]; 276 1.1 leo } 277 1.1 leo 278 1.2 leo int read_block(buf, blkno, drive) 279 1.1 leo void *buf; 280 1.1 leo int blkno; 281 1.1 leo int drive; 282 1.1 leo { 283 1.1 leo if(Dmaread(blkno, 1, buf, drive + 8) != 0) 284 1.1 leo return(0); 285 1.1 leo return(1); 286 1.1 leo } 287 1.1 leo 288 1.2 leo int write_block(buf, blkno, drive) 289 1.1 leo void *buf; 290 1.1 leo int blkno; 291 1.1 leo int drive; 292 1.1 leo { 293 1.1 leo if(Dmawrite(blkno, 1, buf, drive + 8) != 0) 294 1.1 leo return(0); 295 1.1 leo return(1); 296 1.1 leo } 297 1.1 leo 298 1.2 leo void set_csum(buf) 299 1.1 leo char *buf; 300 1.1 leo { 301 1.1 leo unsigned short *p = (unsigned short *)buf; 302 1.1 leo unsigned short csum = 0; 303 1.1 leo int i; 304 1.1 leo 305 1.1 leo p[255] = 0; 306 1.1 leo for(i = 0; i < 256; i++) 307 1.1 leo csum += *p++; 308 1.1 leo *--p = (0x1234 - csum) & 0xffff; 309 1.2 leo } 310 1.2 leo 311 1.6 cegger void usage(void) 312 1.2 leo { 313 1.2 leo eprintf("Usage: %s [-hVwt] [ -o <output file>] <driveno> <partno> " 314 1.2 leo "<newid>\r\n", Progname); 315 1.2 leo xexit(1); 316 1.2 leo } 317 1.2 leo 318 1.2 leo void 319 1.6 cegger help(void) 320 1.2 leo { 321 1.2 leo eprintf("\r 322 1.2 leo Change partition identifiers\r 323 1.2 leo \r 324 1.2 leo Usage: %s [-hVwt] [ -o <output file>] <driveno> <partno> <newid>\r 325 1.2 leo \r 326 1.2 leo Description of options:\r 327 1.2 leo \r 328 1.3 leo \t-h What you're getting right now.\r 329 1.2 leo \t-o Write output to both <output file> and stdout.\r 330 1.2 leo \t-V Print program version.\r 331 1.2 leo \t-w Wait for a keypress before exiting.\r 332 1.2 leo \t-t Test mode. It does everyting except the modifications on disk.\r 333 1.2 leo \r 334 1.2 leo The <driveno> and <partno> arguments specify the drive and the partition\r 335 1.2 leo this program acts on. Both are zero based.\r 336 1.2 leo The <newid> argument specifies a 3 letter string that will become the new\r 337 1.2 leo partition-id.\r 338 1.2 leo Finally note that the actions of %s are reversable.\r 339 1.2 leo ", Progname, Progname); 340 1.2 leo xexit(0); 341 1.1 leo } 342