ftp.nice.ch/pub/next/unix/hack/alphalock.1.0.N.bs.tar.gz#/alphalock.1.0.N.bs/alphalock.c

This is alphalock.c in view mode; [Download] [Up]

/*
**
** NAME
**	alphalock -- disable/enable AlphaLock (Command-Shift) for
**		     NeXT hardware running NeXTSTEP
**		     Release 2.1, 2.2, 3.0, 3.0J, 3.1, or 3.2.
**
** ** = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
** ** UPDATED INFO
** **    Turns out that you don't need to do this patching stuff
** **    (at least not for higher releases of NeXTSTEP).  You
** **    will only see command-shift being treated as shift-lock
** **    if no *other* key is given that function.  So, just use
** **       /NextDeveloper/Demos/Keyboard.app
** **    to create a key-mapping where the function of shift-lock
** **    is assigned to some key combination that you will never
** **    ever hit.
** **
** **    Due to this, which I consider a superior solution anyway,
** **    I doubt I'll ever be doing any new versions of this
** **    alphalock program.              Garance/Jan 27/1997
** ** = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
**
** COMPILE:
**	cc -DDEBUG -s -O -o alphalock alphalock.c
**  or  cc -s -O -object -o alphalock alphalock.c
**
** COMMENTS:
**	Must be run as root!
**      Note that you'd have to compile this on the "least recent"
**         system you're still using (assuming you want to use one
**         binary on all the systems you're running).
**
**	sum of /sdmach used to base this patch:
**		Release 2.1 ->	09308   692
**		Release 2.2 ->	19164   707
**		Release 3.0 ->	40389   784
**		Release 3.1 ->	32892   806
**		Release 3.2 ->  57530   762
**
**	For those technically(?) inclined: check "_CalcModBit" (using
**	otool) in /sdmach and look for code surrounding "_alphaLock"!
**	  hint:   otool -t -V -p _CalcModBit /sdmach | more
**
** AUTHOR
**	Felix A. Lugo     (original version, supported NS 2.1)
**	  coco@ihcoco.att.com
**	Garance A Drosehn (added support for NS 2.2, 3.0, 3.1)
**			  (added "enable" and "disable" parameters)
**			  (added support for NS 3.2)
**	  gad@eclipse.its.rpi.edu
*/


#define EXPORT_BOOLEAN
#include <sys/boolean.h>		//  <mach/boolean.h> in NS3.0
#include <sys/file.h>

#define CHK_COUNT	6		//  # of fullwords we cross-check
#define CHK_PATCH	4		//  subscript of first word to patch
#define CHK_ADDR_V21	0x0405b200	//  start check four fullwords before
#define	PATCH_ADDR_21	0x0405b210	//      the Release 2.1 patch address
#define CHK_ADDR_V22	0x0405cf58	//  start check four fullwords before
#define	PATCH_ADDR_22	0x0405cf68	//      the Release 2.2 patch address
#define CHK_ADDR_V30	0x0406e174	//  start check four fullwords before
#define	PATCH_ADDR_30	0x0406e184	//      the Release 3.0 patch address
#define CHK_ADDR_V31	0x04072ab0	//  start check four fullwords before
#define	PATCH_ADDR_31	0x04072ac0	//      the Release 3.1 patch address
#define CHK_ADDR_V32	0x04073e48	//  start check four fullwords before
#define	PATCH_ADDR_32	0x04073e58	//      the Release 3.2 patch address

#define	PATCH		0x57c07c00	//  value for alphalock neutralized
#define PATCH2		0xC08623C0	//      second word (need for NS3.0)

long	chk_data[CHK_COUNT];
char	rel_matched[10];

boolean_t checkrel( int, long , const long *, const char * );

int
main(int argc, char *argv[])
{
	int	fd;
	long	data[2], orig[2], addr;
	static long chk_21[CHK_COUNT] = 
		{ 0x60224AB9, 0x040A3D80, 0x661A4AB9, 0x040A3D84,
		    /* orig: */		  0x57c07c01, 0xC08623C0 };
	static long chk_22[CHK_COUNT] = 
		{ 0x60304AB9, 0x040A7788, 0x66284AB9, 0x040A778C,
		    /* orig: */		  0x57c07c01, 0xC08623C0 };
	static long chk_30[CHK_COUNT] = 
		{ 0x601A4AB9, 0x040ADF7C, 0x66124AB9, 0x040ADF78,
		    /* orig: */		  0x57c049c0, 0x448023C0 };
	static long chk_31[CHK_COUNT] = 
		{ 0x601A4AB9, 0x040B31CC, 0x66124AB9, 0x040B31C8,
		    /* orig: */		  0x57c049c0, 0x448023C0 };
	static long chk_32[CHK_COUNT] = 
		{ 0x601A4AB9, 0x040B49E0, 0x66124AB9, 0x040B49DC,
		    /* orig: */		  0x57C049C0, 0x448023C0 };
	static long patch[2] =		{ 0x57c07c00, 0xC08623C0 };

	fd = open( "/dev/kmem", O_RDWR );
	if ( fd == -1 ) {
	    printf( "Alphalock must run as root!\n" );
	    exit( 1 );
	    }

	if ( checkrel(fd, CHK_ADDR_V21, chk_21, "2.1" ) ) {
	    addr = PATCH_ADDR_21;
	    orig[0] = chk_21[CHK_PATCH];
	    orig[1] = chk_21[CHK_PATCH+1];
	    }
	else if ( checkrel(fd, CHK_ADDR_V22, chk_22, "2.2" ) ) {
	    addr = PATCH_ADDR_22;
	    orig[0] = chk_22[CHK_PATCH];
	    orig[1] = chk_22[CHK_PATCH+1];
	    }
	else if ( checkrel(fd, CHK_ADDR_V30, chk_30, "3.0" ) ) {
	    /* this also seems to work for 3.0J */
	    addr = PATCH_ADDR_30;
	    orig[0] = chk_30[CHK_PATCH];
	    orig[1] = chk_30[CHK_PATCH+1];
	    }
	else if ( checkrel(fd, CHK_ADDR_V31, chk_31, "3.1" ) ) {
	    addr = PATCH_ADDR_31;
	    orig[0] = chk_31[CHK_PATCH];
	    orig[1] = chk_31[CHK_PATCH+1];
	    }
	else if ( checkrel(fd, CHK_ADDR_V32, chk_32, "3.2" ) ) {
	    addr = PATCH_ADDR_32;
	    orig[0] = chk_32[CHK_PATCH];
	    orig[1] = chk_32[CHK_PATCH+1];
	    }
	else {
	    close( fd );
	    printf( "Unknown kernel for Alphalock!\n" );
	    printf( "(doesn't seem to be any of Release 2.1, 2.2, 3.0, 3.0J, 3.1, or 3.2)\n" );
	    exit( 4 );
	    }

	//  assume the user wants to toggle the setting
	if ( chk_data[CHK_PATCH] == orig[0]
	  && chk_data[CHK_PATCH +1] == orig[1]) {
	    data[0] = patch[0];
	    data[1] = patch[1];
	    }
	else if ( chk_data[CHK_PATCH] == patch[0]
	       && chk_data[CHK_PATCH+1] == patch[1] ) {
	    data[0] = orig[0];
	    data[1] = orig[1];
	    }
	else {
	    close( fd );
	    printf( "Kernel not compatible with Alphalock!\n" );
	    exit( 4 );
	    }

	//  check for explicit request of setting
	if ( argc > 1 ) {
	    if ( !strcmp(argv[1], "enable") ) {
		data[0] = orig[0];
		data[1] = orig[1];
		}
	    else if ( !strcmp(argv[1], "disable") ) {
		data[0] = patch[0];
		data[1] = patch[1];
		}
	    else {
	        printf( "Invalid paramater, expecting \"enable\" or \"disable\"\n" );
		close( fd );
		exit( 5 );
		}
	    }
	
	if ( chk_data[CHK_PATCH] != data[0] ) {
	    if ( lseek( fd, addr, L_SET ) == -1 ) {
		close( fd );
		exit( 6 );
		}
    
	    if ( write( fd, &data, sizeof( data ) ) != sizeof( data ) ) {
		close( fd );
		exit( 7 );
		}
	    }

	close( fd );

	if ( data[0] == patch[0] ) {
	    printf( "AlphaLock on release %s Disabled\n", rel_matched );
	    }
	else {
	    printf( "AlphaLock on release %s Enabled\n", rel_matched );
	    }

	return( 0 );
}


boolean_t
checkrel( 
   int fd, 
   long startchk, 
   const long checkval[CHK_COUNT], 
   const char * rel_char
)
{
    if ( lseek( fd, startchk, L_SET ) == -1 ) {
	close( fd );
	exit( 2 );
	}

    if ( read( fd, chk_data, CHK_COUNT * 4 ) != CHK_COUNT * 4 ) {
	close( fd );
	exit( 3 );
	}

#ifdef DEBUG
    printf( "check %s = %08X %08X %08X %08X - %08X %08X\n", rel_char,
	    chk_data[0], chk_data[1], chk_data[2], chk_data[3],
	    chk_data[4], chk_data[5] );
#endif /* DEBUG */

    if (   (checkval[0] == chk_data[0]) && (checkval[1] == chk_data[1])
	&& (checkval[2] == chk_data[2]) && (checkval[3] == chk_data[3]) 
	) {
#ifdef DEBUG
	printf("Looks like release %s alright\n", rel_char);
#endif /* DEBUG */
	strcpy(rel_matched, rel_char);
	return TRUE ;
    }

    return FALSE ;

}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.