mdapoz@hybrid.UUCP (Mark Dapoz) (09/26/89)
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@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@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@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@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.