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.