Home | History | Annotate | Line # | Download | only in chg_pid
      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