Patch to wind.o to stop cursor from blinking
Mark Dapoz
mdapoz at hybrid.UUCP
Tue Sep 26 13:41:36 AEST 1989
Here's a quick program I wrote to patch the wind.o device driver of the
UNIX PC so that the cursor will become a solid block instead of the usual
(and annoying in my opinion) blinking block. The patch is known to work
with the wind.o driver supplied with the 3.51 version of unix and may or
may not work with older versions. This patch is supplied as is and I don't
guarantee that there aren't any side effects, since modifying device drivers
without source is tricky at best. I suggest you read the ReadMe file if you
have any doubt about what exactly it is I'm doing to the driver. I've been
running with the patch applied for about a week now and I haven't seen any
problems yet so it's probably safe to apply it :-)
Mark Dapoz (mdapoz at hybrid.UUCP) ...uunet!mnetor!hybrid!mdapoz
I remind you that humans are only a tiny minority in this galaxy.
-- Spock, "The Apple," stardate 3715.6.
--- cut here ------ cut here ------ cut here ------ cut here ------ cut here ---
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by mdapoz at hybrid on Mon Sep 25 23:24:30 EDT 1989
# Contents: noblink/ noblink/noblink.c noblink/Makefile noblink/ReadMe
echo mkdir - noblink
mkdir noblink
chmod u=rwx,g=rx,o=rx noblink
echo x - noblink/noblink.c
sed 's/^@//' > "noblink/noblink.c" <<'@//E*O*F noblink/noblink.c//'
/*
noblink.c - modify the standard AT&T UNIX PC wind.o device driver so that
the cursor remains on all the time.
NOTE: this is known to work with version 3.51 and may not work
with earlier (or later if we're lucky enough :-) versions,
although there's a good chance it will.
USE AT YOUR OWN RISK!!! I take no responsibility for anything
that may happen if you use this program. I haven't seen any
side effects from the program but that doesn't mean that it
can't happen!
Mark Dapoz 89/09/25
mdapoz at hybrid.UUCP
*/
#include <stdio.h>
#include <fcntl.h>
#include <nlist.h>
#include <filehdr.h>
#include <scnhdr.h>
#include <aouthdr.h>
#define CCBLINK_MAGIC 0x24 /* magical offset from ccblink label */
#define WUNLOCK_MAGIC 0x6a /* magical offset from wunlock label */
#define WIND_DRIVER "./wind.o"
main(argc, argv)
int argc;
char **argv;
{
struct nlist nl[3]; /* lookup for driver routines */
struct filehdr fh; /* COFF standard file header */
struct scnhdr *shdr; /* COFF section headers */
struct scnhdr *hdr_ptr; /* COFF pointer to section header */
struct aouthdr ohdr; /* COFF optional header */
char buff[32]; /* small buffer for double checking code */
int fd,i,j;
int nmods=0; /* number of successful mods */
/* what code we should see before modifying */
static char ccblink_code[] = {0x67,0x2e,0x42,0x97,0x4e,0xba,0xfe,0xb0,
0x74,0x0f};
static char wunlock_code[] = {0x67,0x0a,0x42,0x39,0x00,0x05,0x97,0xa0,
0x4e,0xba};
/* the code to put on top */
static char ccblink_mod[] = {0x60}; /* 68000 BRA instruction */
static char wunlock_mod[] = {0x4e,0x71};/* 68000 NOP instruction */
/* make sure the user understands the circumstances */
if (getopt(argc, argv, "y") != 'y')
disclaimer();
nl[0].n_name = "ccblink"; /* routine which causes blinking */
nl[1].n_name = "wunlock"; /* also causes blinking at end */
nl[2].n_name = "";
if (nlist(WIND_DRIVER, nl) < 0) { /* locate it in the object file */
perror(argv[0]);
exit(1);
}
#ifdef DEBUG
printf("%s: n_value=0x%x n_scnum=0x%x n_type=0x%x\n",
nl[0].n_name, nl[0].n_value, nl[0].n_scnum, nl[0].n_type);
printf("%s: n_value=0x%x n_scnum=0x%x n_type=0x%x\n",
nl[1].n_name, nl[1].n_value, nl[1].n_scnum, nl[1].n_type);
#endif
if ((fd=open(WIND_DRIVER, O_RDWR)) < 0) {
perror(argv[0]);
exit(1);
}
if (read(fd, &fh, FILHSZ) < 0) { /* get the standard COFF header*/
perror(argv[0]);
close(fd);
exit(1);
}
#ifdef DEBUG
printf("f_magic=0x%x f_nscns=0x%x f_opthdr=0x%x\n",
fh.f_magic, fh.f_nscns, fh.f_opthdr);
#endif
/* allocate room for the section headers */
if ((shdr=(struct scnhdr *)malloc(SCNHSZ*fh.f_nscns)) == NULL) {
perror(argv[0]);
close(fd);
exit(1);
}
if (fh.f_opthdr) /* read any optional headers which may be present */
if (read(fd, &ohdr, sizeof(AOUTHDR)) < 0) {
perror(argv[0]);
close(fd);
exit(1);
}
/* read the COFF section headers */
if (read(fd, shdr, SCNHSZ*fh.f_nscns) < 0) {
perror(argv[0]);
close(fd);
exit(1);
}
/* run through all the sections */
for (i=0,hdr_ptr=shdr; i < fh.f_nscns; i++,hdr_ptr++) {
#ifdef DEBUG
printf("s_name=%s s_size=0x%x s_scnptr=0x%x s_vaddr=0x%x\n",
hdr_ptr->s_name, hdr_ptr->s_size, hdr_ptr->s_scnptr,
hdr_ptr->s_vaddr);
#endif
if (i+1 == nl[0].n_scnum) { /* look for "ccblink" routine */
if (strcmp(hdr_ptr->s_name, _TEXT)) {
printf("'ccblink' routine not in a .text section\n");
continue;
}
/* jump to magical place (Mr Rogers?)*/
if (lseek(fd, hdr_ptr->s_scnptr-hdr_ptr->s_vaddr+nl[0].n_value+
CCBLINK_MAGIC, 0) < 0) {
perror(argv[0]);
break;
}
/* read in code from offset */
if (read(fd, buff, 32) < 0) {
perror(argv[0]);
close(fd);
exit(1);
}
#ifdef DEBUG
printf("ccblink mod =0x%x\n", buff[0]);
#endif
for (j=0; j < 10; j++)
if (buff[i] != ccblink_code[i]) {
printf("ccblink routine not as expected, aborting!\n");
exit(1);
}
/* jump to magical place again */
if (lseek(fd, hdr_ptr->s_scnptr-hdr_ptr->s_vaddr+nl[0].n_value+
CCBLINK_MAGIC, 0) < 0) {
perror(argv[0]);
break;
}
/* make the code modification */
if (write(fd, ccblink_mod, 1) < 0) {
perror(argv[0]);
close(fd);
exit(1);
}
nmods++; /* indicate successful modification */
}
if (i+1 == nl[1].n_scnum) { /* look for "wunlock" routine */
if (strcmp(hdr_ptr->s_name, _TEXT)) {
printf("'wunlock' routine not in a .text section\n");
continue;
}
/* jump to magical place (Mr Rogers?)*/
if (lseek(fd, hdr_ptr->s_scnptr-hdr_ptr->s_vaddr+nl[1].n_value+
WUNLOCK_MAGIC, 0) < 0) {
perror(argv[0]);
break;
}
/* read in code from offset */
if (read(fd, buff, 32) < 0) {
perror(argv[0]);
close(fd);
exit(1);
}
#ifdef DEBUG
printf("wunlock mod =0x%x\n", buff[0]);
#endif
for (j=0; j < 10; j++)
if (buff[i] != wunlock_code[i]) {
printf("wunlock routine not as expected, aborting!\n");
exit(1);
}
/* jump to magical place again */
if (lseek(fd, hdr_ptr->s_scnptr-hdr_ptr->s_vaddr+nl[1].n_value+
WUNLOCK_MAGIC, 0) < 0) {
perror(argv[0]);
break;
}
/* make the code modification */
if (write(fd, wunlock_mod, 2) < 0) {
perror(argv[0]);
close(fd);
exit(1);
}
nmods++; /* indicate successful modification */
}
}
if (nmods == 2)
printf("Driver successfully modified\n");
else
printf("Driver modification failed\n");
free(shdr); /* be nice and return allocated memory */
close(fd); /* and close up the file */
}
disclaimer()
{
fprintf(stderr, "NOTE: this program will attempt to modify your window device driver and leave\n");
fprintf(stderr, "behind a patched copy which produces a steady solid block cursor instead of the\n");
fprintf(stderr, "blinking cursor. Since this involves patching the binary for the device driver\n");
fprintf(stderr, "the author does NOT assume any responsibily for problems which may occur.\n");
fprintf(stderr, "It's HIGHLY recommended you have a floppy unix ready for backout purposes.\n");
fprintf(stderr, "\nUSE AT YOUR OWN RISK!!!!\n");
fprintf(stderr, "\nPlease enter 'noblink -y' to indicate you understand this.\n");
exit(0);
}
@//E*O*F noblink/noblink.c//
chmod u=rw,g=r,o=r noblink/noblink.c
echo x - noblink/Makefile
sed 's/^@//' > "noblink/Makefile" <<'@//E*O*F noblink/Makefile//'
CC=cc
CFLAGS=
all: noblink
/bin/cp /etc/lddrv/wind.o ./wind.o
@./noblink
@/bin/echo
@/bin/echo "When the driver is successfully modified, enter 'make install' to install"
@/bin/echo "the modified driver (you will need to be 'root' to do this)."
noblink: noblink.o
$(CC) $(LDFLAGS) noblink.o -o noblink
install:
/bin/ln /etc/lddrv/wind.o /etc/lddrv/wind.o.orig
/bin/rm /etc/lddrv/wind.o
/bin/cp ./wind.o /etc/lddrv/wind.o
-/bin/rm /etc/lddrv/wind
@/bin/echo
@/bin/echo "The new driver has been installed. A copy of the old one can be found in"
@/bin/echo "/etc/lddrv/wind.o.orig."
@/bin/echo
@/bin/echo "You will need to reboot your system to pick up the new device driver."
clean:
/bin/rm noblink.o noblink wind.o
clobber: clean
@//E*O*F noblink/Makefile//
chmod u=rw,g=r,o=r noblink/Makefile
echo x - noblink/ReadMe
sed 's/^@//' > "noblink/ReadMe" <<'@//E*O*F noblink/ReadMe//'
NoBlink - a program to stop the blinking of the cursor on the console of the
UNIX PC
This is a quick description of what the noblink program really does. Since this
program modifies a device driver, you should be somewhat competent in how the
UNIX PC manages loadable device drivers. If you don't know what a device
driver is, stop here, go no further, don't pass go and don't collect $200. It's
very easy to get yourself into a bind (no pun intended :-) when moving device
drivers around, so you should at least know how to boot off a floppy unix and
be able to restore the original driver in case of problems. Enough warnings,
on to the real stuff.
If you were to disassemble the wind.o device driver, you would find that there
are two routines which primarily control the blinking of the cursor. The
first routine "ccblink" is an interrupt driven routine called by the timeout()
device driver call. This routine is called twice per second and controls the
blink rate of the cursor. Below is the disassembled routine:
global ccblink
ccblink:
link %fp,&-12
movm.l &0x4,-4(%fp) # %d2
mov.l &30,%d2 # blink rate in 60 Hz (ie. 1/2 second)
jsr spl6
mov.l %d0,-8(%fp)
tst.w winlock
bne TS321
tst.b ccvis
# beq TS322 # **modified** branch always
bra TS322 # skip blanking the cursor
clr.l (%sp)
jsr ccset
mov.l &15,%d2
TS321:
mov.l -8(%fp),(%sp)
jsr splx
mov.l %d2,(%sp)
clr.l -(%sp)
mov.l ccblink,-(%sp)
jsr timeout
add.w &8,%sp
movm.l -4(%fp),&0x4 # %d2
unlk %fp
rts
TS322:
jsr ccon
bra TS321
You'll notice that there is a variable called ccvis which indicates if the
cursor is visible or not. This variable is controlled by the ccset routine
(not provided here) which does the actual clearing/displaying of the cursor.
By modifying "ccblink", we can prevent the cursor from being blanked by
always making the test of ccvis succeed. This will catch about 90% of the
blanking of the cursor. The remainder of the blanking takes place in the
"wunlock" routine. I beleive this routine is used for locking updates to
the screen within the device driver. The disassembled code for this routine
is as follows:
global wunlock
wunlock:
link %fp,&-4
tst.w winlock
bne TS128
mov.l RS2,(%sp)
jsr panic
TS128:
tst.l scrticks
beq TS129
mov.l lbolt,%d0
sub.l ktime,%d0
cmp.l %d0,scrticks
ble TS129
tst.b scrsav
bne TS130
jsr savscrn
bra TS130
TS129:
cmp.l winscreen+0x90004,&0x420000
beq TS130
jsr usavscrn
TS130:
tst.b omsvis
beq TS131
mov.l &1,%d0
mov.l %d0,(%sp)
jsr msset+0x832ea
TS131:
tst.b forceon
# beq TS132 # **modified**
nop # force cursor redisplay on every entry
clr.b forceon
jsr ccon
TS132:
clr.w winlock
mov.l winlock,(%sp)
jsr wakeup
unlk %fp
rts
You'll notice that there is an additional variable called forceon which controls
whether or not "wunlock" causes the cursor to be redisplayed. By modifying
the result of the comparison of this variable, we can cause the cursor to be
redisplayed whenever the screen is unlocked. This provides us with a full
cursor for the remaining 10% of the time.
One small note should be made now. You'll probably notice that the cursor tends
to flicker every now and then. This can be attributed to the fact that several
areas of the screen must continually be updated; the top status line which
contains the clock is one such area. When these areas are updated, the cursor
must be "moved" to the area being written to, and as a result you notice a
temporary flicker of the cursor. You'll also notice this behaviour on most
ascii terminals.
Mark Dapoz
...uunet!mnetor!hybrid!mdapoz
@//E*O*F noblink/ReadMe//
chmod u=rw,g=r,o=r noblink/ReadMe
echo Inspecting for damage in transit...
temp=/tmp/shar$$; dtemp=/tmp/.shar$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
202 814 6413 noblink.c
28 95 755 Makefile
124 593 3624 ReadMe
354 1502 10792 total
!!!
wc noblink/noblink.c noblink/Makefile noblink/ReadMe | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if [ -s $dtemp ]
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0
--
Mark Dapoz (mdapoz at hybrid.UUCP) ...uunet!mnetor!hybrid!mdapoz
I remind you that humans are only a tiny minority in this galaxy.
-- Spock, "The Apple," stardate 3715.6.
More information about the Unix-pc.sources
mailing list