EXECUTABLE BOOTSECTORS by Guus Surtel There are some utilities people always prefer to run before doing anything else with their Atari ST. For example a utility that sets the date or sets the sync to 60hz. Because they always want to run it before anything else they put those utilities into an auto folder. The advantage of an auto folder is that you don't have to click on the programs in order to start them, the system automatically starts them while bootting. A disadvantage of this system is that it costs diskspace and you always have to copy the auto folder and its contents to a new disk. When I read about executable bootsectors, I thought it would be nice to put some standard routines into the bootsector, so that each time the system restarts it will execute those utilities. First I will tell you what is in the bootsector. Bytes Meaning ===== ======= 0 - 1 Machinecode branch instruction to the beginning of the executable machinecode in this sector. 2 - 7 Reserved (at the moment equal to the virgin data 4E). 8 - A Serial number of this disk. The only way that the operating system knows that you have change the disk is by means of the serial number. The serial number is also used in a number of copy protection schemes. B - C Bytes/Sector. Low byte first for MS-DOS compatibility. D Number of sectors/clusters (normally 2) E - F The number of reserved sector. 10 The number of FAT's (File Allocation Tables). 11-12 The number of directory entries. Low byte first 13-14 The number of sectors on the disk. 15 Media descriptor (Not used by the Atari ST). 16-17 The number of sectors in each FAT. 18-19 The number of sectors per track (normally 9). 1A-1B The number of sides on the disk (normally 1 or 2). 1C-1D The number of hidden sectors (Not used by the Atari). 1E-1FD Boot code (if any) 1FE-1FF Checksum of bootsector. If this checksum=$1234 then this is an executable bootsector. In order to create a executable bootsector we read the existing bootsector, modify it and write the bootsector back. We can read and write the bootsector with the relevant XBIOS routines (FLOPRD and FLOPWR). In order to make the bootsector executable we put the machinecode into the area from 1E till 1FF in the bootsector and put a branch instruction to the beginning of the machinecode (BRA $1C) at position 0. Then the prototype routine is called to generate the required checksum for a bootsector. The assembly source code (for the Metacomco Assembler) supplied contains a routine called EXECUTE. This routine is copied into the bootsector. You can easily extend or replace this routine with some new, useful routines. The EXECUTE routine now contains a routine to set the printer parameters (so I can get good hardcopies of the screen), a routine to copy the date and time of the keyboard processor to GEM (you now only have to set the date and time once, when you power up your computer) and a routine to change the screen synchronisation (to 60hz in my case). The program is very simple to use. Just start it and insert the disk you want to modify. All information (except a possible machinecode routine in the bootsector) is left untouched. Originally published in ST NEWS Volume 2 Issue 5. ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo *********************************************** ********* Assembly Source Code Listing ******** *********************************************** * ADD A MACHINECODE ROUTINE TO THE BOOTSECTOR * * by Guus Surtel. * * Originally published in the ST NEWS * * Volume 2 Issue * *********************************************** STACK EQU 4000 GEMDOS EQU $01 CCONIN EQU $01 CRAWCIN EQU $07 CCONWS EQU $09 TSETDATE EQU $2B TSETTIME EQU $2D M_SHRINK EQU $4A XBIOS EQU $E FLOPRD EQU 8 FLOPWR EQU 9 PROTOBT EQU 18 GETTIME EQU 23 SETPRT EQU 33 * MEMORY MANAGEMENT AND INITIALISATION MOVE.L 4(A7),A0 * FETCH BASEPAGE MOVE.L $C(A0),D0 * LENGTH OF TEXT MOVE.L $14(A0),D0 * LENGTH OF DATA MOVE.L $1C(A0),D0 * LENGTH OF BSS ADD.L #$100,D0 * BASEPAGE SIZE ADD.L #STACK,D0 * STACK SIZE MOVE.L A0,A7 * SET THE STACK ADD.L D0,A7 MOVE.L D0,-(A7) * ONLY ALLOCATE AS MUCH SPACE MOVE.L A0,-(A7) * AS WE ARE USING CLR.W -(A7) MOVE.W #M_SHRINK,-(A7) TRAP #GEMDOS LEA 12(A7),A7 * DISPLAY TEXT AGAIN PEA OPEN_MSG MOVE.W #CCONWS,-(A7) TRAP #GEMDOS ADDQ.L #6,A7 * WAIT FOR A KEY MOVE.W #CRAWCIN,-(A7) TRAP #GEMDOS ADDQ.L #2,A7 * READ THE BOOTSECTOR MOVE.W #1,-(A7) * ONE SECTOR TO READ CLR.W -(A7) * SELECT SIDE 0 CLR.W -(A7) * SELECT TRACK 0 MOVE.W #1,-(A7) * SELECT SECTOR 1 CLR.W -(A7) * SELECT DISKDRIVE A CLR.L -(A7) * FILLER PEA BUFFER * START OF THE BUFFER MOVE.W #FLOPRD,-(A7) TRAP #XBIOS LEA 20(A7),A7 TST.L D0 BEQ.S READ_OK * ERROR WHILE READING PEA READ_ERR MOVE.W #CCONWS,-(A7) TRAP #GEMDOS ADDQ.L #6,A7 BRA.S NEXT * COPY THE MACHINECODE ROUTINE INTO THE BOOTSECTOR READ_OK MOVE.L #BUFFER,A0 MOVE.W #$601C,(A0) * BRANCH TO THE BEGIN OF THE CODE LEA $1E(A0),A0 * START OF BOOTCODE AREA MOVE.L #EXECUTE,A1 * START OF MACHINECODE MOVE.W #119,D0 * MAXIMUM LENGTH OF THE MACHINECODE COPY_NEXT MOVE.L (A1)+,(A0)+ DBF D0,COPY_NEXT * MAKE THE BOOTSECTOR EXECUTABLE MOVE.W #1,-(A7) * MAKE EXECUTABLE MOVE.W #-1,-(A7) * LEAVE DISKTYPE ALONE MOVE.L #-1,-(A7) * LEAVE SERIALNUMBER ALONE PEA BUFFER * START OF THE BUFFER MOVE.W #PROTOBT,-(A7) TRAP #XBIOS LEA 14(A7),A7 * WRITE THE BOOTSECTOR TO THE DISK MOVE.W #1,-(A7) * ONE SECTOR TO WRITE CLR.W -(A7) * SELECT SIDE 0 CLR.W -(A7) * SELECT TRACK 0 MOVE.W #1,-(A7) * SELECT SECTOR 1 CLR.W -(A7) * SELECT DISKDRIVE A CLR.L -(A7) * FILLER PEA BUFFER * START OF THE BUFFER MOVE.W #FLOPWR,-(A7) TRAP #XBIOS LEA 20(A7),A7 TST.L D0 BEQ.S NEXT * ERROR WHILE WRITING PEA WRITE_ERR MOVE.W #CCONWS,-(A7) TRAP #GEMDOS ADDQ.L #6,A7 * "RUN PROGRAM AGAIN ?" MESSAGE NEXT PEA AGAIN_MSG MOVE.W #CCONWS,-(A7) TRAP #GEMDOS ADDQ.L #6,A7 * GET A KEY MOVE.W #CCONIN,-(A7) TRAP #GEMDOS ADDQ.L #2,A7 AND.B #%01011111,D0 CMP.B #"Y",D0 BEQ AGAIN * END OF PROGRAM CLR.W -(A7) TRAP #GEMDOS * HERE FOLLOWS THE MACHINECODE ROUTINE THAT MUST BE INCORPORATED INTO * THE BOOTSECTOR. REMEMBER THE FOLLOWING POINTS: * - THE LENGTH MAY NOT EXCEED 480 BYTES * - THE MACHINECODE MUST BE POSITION INDEPENDED * - THE MACHINECODE MUST BE FINISHED WITH AN RTS INSTRUCTION * - DON'T USE GEM OR VDI ROUTINES * - THE MACHINECODE IS EXECUTED IN SUPERVISORMODE, DON'T CHANGE THE MODE EXECUTE: * SET THE PRINTER CONFIGURATION MOVE.W #%101110,-(A7) MOVE.W #SETPRT,-(A7) TRAP #XBIOS ADDQ.L #4,A7 * COPY THE KEYBOARD PROCESSOR TIME AND DATE TO GEM MOVE.W #GETTIME,-(A7) TRAP #XBIOS ADDQ.L #2,A7 MOVE.W D0,-(A7) SWAP D0 MOVE.W D0,-(A7) MOVE.W #TSETDATE,-(A7) TRAP #GEMDOS ADDQ.L #4,A7 MOVE.W #TSETTIME,-(A7) TRAP #GEMDOS ADDQ.L #4,A7 * FIDDLE THE HZ MOVE.B $FFFF820A,D7 EOR.B #%10,D7 * lea 4(pc),a6 DC.W $4DFA * MY ASSEMBLER GOT PROBLEMS DC.W $0004 * WITH LEA 4(PC),A6 BRA.S TIME_DUM MOVE.B D7,$FFFF820A RTS TIME_DUM LEA $FFFFFA21,A0 LEA $FFFFFA1B,A1 MOVE.B #$10,(A1) MOVEQ.L #1,D4 MOVE.B #0,(A1) MOVE.B #$F0,(A0) MOVE.B #$8,$FFFFFA1B WAIT_1 MOVE.B (A0),D0 CMP.B D4,D0 BNE.S WAIT_1 WAIT_2 MOVE.B (A0),D4 MOVE.W #$267,D3 WAIT_3 CMP.B (A0),D4 BNE.S WAIT_2 DBF D3,WAIT_3 MOVE.B #$10,(A1) JMP (A6) * INITIALISED DATA DATA OPEN_MSG DC.B 27,'E' DC.B "**********************************",13,10 DC.B "* *",13,10 DC.B "* BOOTSECTOR MODIFIER *",13,10 DC.B "* *",13,10 DC.B "* (C) Guus Surtel 1987 *",13,10 DC.B "* *",13,10 DC.B "**********************************",13,10 DC.B 13,10,13,10 DC.B "Insert the disk to be modified and press return..." DC.B 0 READ_ERR DC.B 13,10 DC.B "Error while reading !" DC.B 0 WRITE_ERR DC.B 13,10 DC.B "Error while writing !" DC.B 0 AGAIN_MSG DC.B 13,10 DC.B "Would you like to run this program again ? (y/n) " DC.B 0 * UNITIALISED DATA BSS BUFFER DS.W 256 * END OF THE PROGRAM END