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