1 /SERIAL DISK BOOT 2 / 3 /VER 1.0 20210209 4 / 5 / WRITTEN BY DOUG INGRAHAM FEB 4TH THROUGH 9TH OF 2021. 6 / 7 / SPECIAL THANKS TO KYLE OWEN AND VINCE SLYNGSTAD. TO KYLE FOR 8 / MENTIONING THE HELP LOADER. I DON'T KNOW THAT I WOULD HAVE WORKED ON 9 / THIS WITHOUT HIS PROMPTING. VINCE LOOKED OVER THE CODE SEVERAL TIMES 10 / FINDING BUGS AND MAKING SUGGESTIONS THAT GREATLY AIDED THE PROCESS. I 11 / HAD ALMOST GIVEN UP UNTIL HE POINTED OUT THAT I COULD INSERT A 12 / JMP I GETCH IN THE BOOT 1 CODE REMNANT FROM BOOT 2 AND CALL THAT TO 13 / READ CHARACTERS FROM THE SERVER. THIS SAVED JUST ENOUGH SPACE TO MAKE 14 / IT POSSIBLE. 15 / 16 / THIS BOOT LOADER IS THE SHORTEST TOGGLE IN SEQUENCE KNOWN FOR NON DATA 17 / BREAK DEVICES. IT IS INTENDED TO BE USED WITH AN 8 BIT INTERFACE LIKE 18 / A SERIAL PORT. IT IS BASED ON THE TECHNIQUES FOUND IN THE DEC HELP 19 / LOADER. IT ENDS UP BEING A THREE STAGE BOOT WHERE EACH STAGE REMOVES 20 / SOME LIMITATIONS IMPOSED BY THE PREVIOUS STAGE. THE GOAL IS TO 21 / REQUIRE THE LEAST AMOUNT OF SWITCH FLIPPING IN ORDER TO LOAD A PROGRAM 22 / OR BRING UP AN OPERATING SYSTEM LIKE OS/8. 23 24 / THE BOOT 1 PROGRAM: 25 / 26 / SENDS A 0 TO THE SERVER AS A WAKEUP CODE. 27 / THEN WAITS FOR A SERIES OF 8 BIT CODES WHICH ARE CONVERTED INTO 12 BIT 28 / INSTRUCTIONS THAT ARE PLACED INTO SUCCESIVE MEMORY LOCATIONS STARTING 29 / WITH ADDRESS 0001. THIS CONTINUES UNTIL THE FIRST INSTRUCTION OF THE 30 / BOOT 1 PROGRAM'S MAIN LOOP IS OVERWRITTEN BY A JMP TO THE START OF THE 31 / BOOT 2 PROGRAM. EXECUTION THEN CONTINUES WITH THE BOOT 2 PROGRAM. 32 / 33 / THE 8 BIT HELP CODES SENT ARE CONVERTED TO 12 BIT INSTRUCTIONS WHICH 34 / HAVE SOME SEVERE LIMITATIONS ON THE CODE BOOT 1 LOADS. 35 / * MEMORY REFERENCE INSTRUCTIONS CAN ONLY DIRECTLY ADDRESS MEMORY FROM 36 / 000 THROUGH 037. NO INDIRECT OR CURRENT PAGE REFERENCES! 37 / * IOT'S CAN ONLY ADDRESS DEVICE CODES 0 THROUGH 3. 38 / * FOR THE OPERATE INSTRUCTIONS YOU CAN ONLY GENERATE GROUP 1 AND NOT 39 / ALL ENCODINGS CAN BE USED. CML, RAR, RAL, RTR, RTL, AND IAC ARE 40 / ALLOWED. YOU CAN'T SPECIFY CLA, CLL, OR CMA OPERATIONS. 41 / FORTUNATELY THIS STILL LEAVES A LOT OF POSSIBILITIES BUT YOU ARE 42 / BASICALLY LIMITED TO THE BOTTOM 32 WORDS OF MEMORY AND NO INDIRECTION 43 / WHICH ALSO MEANS NO SUBROUTINES BECAUSE THE RETURN REQUIRES 44 / INDIRECTION. 45 46 / THE BOOT 2 PROGRAM: 47 48 / THE BOOT 2 PROGRAM REQUIRES INDIRECTION IN 3 PLACES. WHEN IT STARTS 49 / IT DOES NOT HAVE ANY DUE TO THE LIMITATIONS OF THE HELP LOADER. TO 50 / MAKE MATTERS WORSE IT CANNOT EVEN RECEIVE CODES FROM THE SERVER. THIS 51 / IS DUE TO THE LIMITATIONS ON THE IOT DEVICE CODES THAT THE HELP LOADER 52 / CAN GENERATE. THE FIRST ORDER OF BUSINESS IS TO TALK TO THE SERVER 53 / WHICH WILL ALLOW THE BOOT 2 CODE TO PATCH ITSELF. THERE IS A THREE 54 / INSTRUCTION SEQUENCE IN THE BOOT 1 CODE WHICH WAITS FOR A CHARACTER 55 / FROM THE SERVER. A JMP I TO THE CORRECT PLACE AT THE CORRECT PLACE 56 / WILL TURN THOSE 3 INSTRUCTIONS INTO A SUBROUTINE WHICH THE BOOT 2 CODE 57 / CAN CALL. THE 4 INSTRUCTIONS STARTING AT PATCH BUILD THE JMP I GETCH 58 / INSTRUCTION AND INSTALL IT AT THE CORRECT LOCATION IN THE OLD BOOT 1. 59 / PATCH CODE NEEDS THE LINK TO BE LEFT CLEAR BY BOOT1 WHEN IT EXITS BUT 60 / THIS SHOULD BE THE NORMAL SITUATION. THE OTHER 2 LOCATIONS REQUIRING 61 / A PATCH TO ALLOW INDIRECTION WILL SELF PATCH THE FIRST TIME THEY ARE 62 / ENCOUNTERED. THE FIRST OF THESE IS THE RETURN IN THE GETNUM 63 / SUBROUTINE. THE PLACEHOLDER FOR THE JMP I GETNUM IS A DCA . WHICH 64 / WILL OVERWRITE ITSELF WITH THE VALUE SENT BY THE SERVER. IN THIS 65 / FIRST CALL IT WONT BE ABLE TO RETURN BUT THE JMP PATCH THAT FOLLOWS IT 66 / WILL BE TAKEN AND A HARMLESS REPATCH WILL TAKE PLACE. THE LAST 67 / INDIRECT REFERENCE IS FOUND IN THE BOOT2 LOOP AND IS THE INSTRUCTION 68 / THAT WILL STORE THE WORD AT STRADR. IT TOO IS A DCA . BEFORE IT SELF 69 / PATCHES TO A DCA I STRADR INSTRUCTION. AFTER THIS BOOT 2 IS READY TO 70 / ACCEPT ADDRESS/DATA PAIRS AND LOAD UP THE BOOT 3 INSTRUCTIONS. WHEN 71 / ALL THE BOOT 3 INSTRUCTIONS ARE RECEIVED THE SERVER WILL OVERWRITE THE 72 / JMP AT THE END OF THE BOOT2 LOOP WITH A JMP TO THE BOOT 3 ENTRY POINT. 73 / BOOT 2 IS NOT ABLE TO WRITE TO ANYTHING BUT FIELD 0 AND SENDING THE 74 / ADDRESS/DATA PAIRS IS ABOUT HALF AS FAST AS DOING A BLOCK TRANSFER. 75 / FOR THESE TWO REASONS THE ONLY THING BOOT 2 IS USED FOR IS TO LOAD THE 76 / MORE CAPABLE LOADER CALLED BOOT 3. 77 78 / THE BOOT 3 PROGRAM: 79 80 / BOOT 3 IS PASSED THREE ARGUMENTS FOLLOWED BY A VARIABLE NUMBER OF DATA 81 / WORDS THAT WILL BE COPIED INTO MEMORY. 82 / ARG1 IS THE STARTING ADDRESS. 83 / ARG2 IS THE TWO'S COMPLEMENT OF THE WORD COUNT WHERE 0 IS 4096. 84 / ARG3 IS AN INSTRUCTION THAT IS IMMEDIATLY EXECUTED. THE INTENTION FOR 85 / THIS IS TO ALLOW THE DATA TO BE WRITTEN TO OTHER FIELDS. IN THAT CASE 86 / THE INSTRUCTION WILL BE A CDF. THE OTHER COMMON USE WILL BE TO 87 / TRANSFER CONTROL TO SOME PROGRAM JUST LOADED. IN THAT CASE THIS WILL 88 / MOST LIKELY BE A JMP I STRADR WHICH WILL JMP TO THE ADDRESS LOADED IN ARG1. 89 / THE THREE COMMON CODES ARE: 90 / CDF 00 6201 SELECT FIELD 0 91 / CDF 10 6211 SELECT FIELD 1 92 / JMP I 2 5402 JMP TO ARG1 THE WORD COUNT IS IGNORED. 93 94 / WHAT IS EXPECTED OF THE SERVER: 95 96 / THE BOOT 1 CODE WILL SEND A 000 TO THE SERVER TO INDICATE BOOT. 97 / THE SERVER WILL SEND THE HELPER CODE FOR BOOT 2 AS FOLLOWS: 98 99 / ADR HLP INST 100 / 01 000 0000 101 / 02 004 0000 102 / 03 326 5032 103 / 04 327 7032 104 / 05 127 7012 105 / 06 034 1003 106 / 07 361 3036 107 / 10 206 4020 108 / 11 021 3002 109 / 12 206 4020 110 / 13 135 3013 111 / 14 102 5010 112 / 15 000 0000 113 / 16 000 0000 114 / 17 000 0000 115 / 20 000 0000 116 / 21 326 4032 117 / 22 067 7006 118 / 23 067 7006 119 / 24 067 7006 120 / 25 001 3000 121 / 26 326 4032 122 / 27 004 1000 123 / 30 305 3030 124 / 31 032 5003 / Gets incremented after it is loaded 125 / -- 000 0000 / Gets loaded in AC prior to executing JMP PATCH 126 127 / THE ABOVE TABLE IS THE ADDRESS, THE HELP CODE THE SERVER SENDS AND THE 128 / INSTRUCTION THAT WILL GO IN MEMORY AFTER THE BOOT 1 CONVERSION. 129 130 / THE LAST HELPER CODE SENT ABOVE WILL BE A JMP TO THE BOOT 2 LOADER. 131 / THIS JMP OVERWRITE THE FIRST INSTRUCTION IN THE BOOT 1 MAIN LOOP WHICH 132 / WILL CAUSE CONTROL TO PASS TO BOOT 2. 133 / THEN THE SERVER WILL SEND A 5420 (JMP I GETNUM) TO PATCH IN THE RETURN 134 / FOR GETNUM. 135 / BOOT 2 IS NOT YET COMPLETELY PATCHED SO A WORD WILL NEED TO BE SENT 136 / THAT WILL BE STORED IN STRADR BUT NOT USED. 137 / THEN THE SERVER WILL SEND A 3402 (DCA I STRADR) TO PATCH IN THE 138 / INDIRECT STORE IN THE MAIN LOOP. 139 / THE BOOT 2 CODE IS NOW UP AND RUNNING. 140 / THE SERVER CAN NOW SEND THE BOOT 3 LOADER AND FORCE A JMP TO IT. 141 142 / HERE IS THE CODE FOR THE BOOT 3 LOADER SENT AS PAIRS: 143 / 0041 4020 144 / 0042 3002 145 / 0043 4020 146 / 0044 3001 147 / 0045 4020 148 / 0046 3047 149 / 0047 0000 150 / 0050 4020 151 / 0051 3402 152 / 0052 2002 153 / 0053 2001 154 / 0054 5050 155 / 0055 5041 156 / NEXT WE NEED TO TRANSFER CONTROL TO ADDRESS 0041 WHICH IS THE START OF 157 / THE BOOT 3 LOADER. 158 / 0014 5041 159 160 / NOW BOOT 3 IS RUNNING. IN ORDER TO BOOT OS/8 THE SERVER NEEDS TO READ 161 / THE BOOT BLOCK AND MAKE TWO CALLS TO BOOT 3 TO LOAD THE RESIDENT 162 / PORTIONS OF OS/8. THE FIRST BLOCK WILL BEGIN AT WORD 0047 OF THE BOOT 163 / BLOCK AND BE WRITTEN TO FIELD 1 STARTING AT 7647 AND CONSIST OF 0131 164 / WORDS (TWO'S COMPLEMENT IS 7647). 165 / ARG1 WILL BE 7647. 166 / ARG2 WILL BE 7647. 167 / ARG3 WILL BE 6211. 168 / THE NEXT 89 WORDS SENT WILL BE FROM THE BOOT BLOCK STARTING AT 0047. 169 / THE SECOND CALL TO BOOT 3 WILL TRANSFER THE OTHER 2ND HALF OF THE BOOT 170 / BLOCK TO FIELD 0 STARTING AT 7600. 171 / ARG1 WILL BE 7600. 172 / ARG2 WILL BE 7600. 173 / ARG3 WILL BE 6201. 174 / THE NEXT 128 WORDS SENT WILL BE FROM THE BOOT BLOCK STARTING AT 0200. 175 / THE FINAL CALL TO BOOT 3 WILL BE TO EFFECT A TRANSFER OF CONTROL TO THE OS/8 ENTRY POINT AT 176 000000 7605 7605. 177 / ARG1 WILL BE 7605. (ADDRESS OF OS/8 ENTRY POINT) 178 / ARG2 WILL BE 0000. (DOESN'T ACTUALLY MATTER AS IT IS NOT USED.) 179 / ARG3 WILL BE 5402. (JMP I STRADR AND OS/8 SHOULD START) 180 181 182 / A WORD ABOUT THE .-. CONSTRUCT. 183 184 / I SAW THIS IN SOME CODE I WAS READING A VERY LONG TIME AGO AND DECIDED 185 / TO USE IT LIKE THEY WERE. AS A PLACEHOLDER FOR SELF MODIFYING CODE OR 186 / THE RETURN ADDRESS LOCATION OF A SUBROUTINE. IT STANDS OUT FROM THE 187 / TEXT AROUND IT SO IT CATCHES YOUR EYE AND YOU KNOW SOMETHING 188 / INTERESTING IS HAPPENING HERE. THE CALCULATION IS CURRENT ADDRESS 189 / MINUS CURRENT ADDRESS WHICH IS ZERO. 190 191 / DEFINE THE IOT INSTRUCTIONS 192 SKSF=6401 193 SKRB=6406 194 STLS=6416 195 196 *0000 197 000000 0000 TEMP, .-. /UPPER HALF OF 12 BITS GETS STORED HERE 198 000001 0000 WC, .-. /WORD COUNT FOR BLOCK TRANSFER 199 000002 0000 STRADR, .-. /ADDRESS WHERE DATA WILL BE STORED 200 201 / FIRST WE MAKE A GET CHARACTER SUBROUTINE OUT OF THE BOOT 1 CODE BY 202 / CREATING A JMP I GETCH TO PERFORM THE RETURN. 203 000003 5032 JPATCH, JMP GETCH /CONSTANT FOR PATCHING 204 PATCH, /THE LAST HELPER CODE MUST LEAVE THE LINK CLEAR! 205 000004 7032 CML RTR /GENERATE A 0400 WHICH IS THE INDIRECT BIT 206 000005 7012 RTR 207 000006 1003 TAD JPATCH 208 000007 3036 DCA PTCHME /NOW GETCH IS A CHAR FETCH SUBROUTINE. 209 210 / THIS IS THE MAIN LOOP OF BOOT 2. IT ACCEPTS PAIRS OF WORDS. THE 211 / FIRST IS THE ADDRESS WHERE THE SECOND WILL BE STORED. IT CAN ONLY 212 / WRITE TO FIELD 0. THE FIRST TIME THROUGH THE 1ST WORD RECEIVED WILL 213 / BE STORED IN STRADR BUT WILL NOT BE USED. THE 2ND WORD SENT WILL NEED 214 / TO BE THE VALUE FOR DCA I STRADR (3402). THE DCA . WILL OVERWRITE 215 / ITSELF WITH THE DCA I STRADR INSTRUCTION. THE BOOT2 PROGRAM IS NOW 216 / COMPLETELY PATCHED. FOR PERFORMANCE REASONS IT SHOULD BE USED TO LOAD 217 / THE BOOT3 PROGRAM. CONTROL IS EASILY TRANSFERED BY OVERWRITING THE 218 / JMP BOOT2 AT ADDRESS 0014 WITH A JMP BOOT3 (5041) INSTRUCTION. 219 220 000010 4020 BOOT2, JMS GETNUM /FETCH A 12 BIT VALUE 221 000011 3002 DCA STRADR /SAVE THE STORE ADDRESS 222 000012 4020 JMS GETNUM /FETCH ANOTHER 12 BIT VALUE 223 000013 3013 DCA . /THIS GETS PATCHED TO A DCA I STRADR 224 /WHICH STORES THE VALUE AT STRADR 225 000014 5010 JMP BOOT2 /DO THE NEXT ONE 226 227 000015 0000 ZBLOCK 0020-. /GETNUM MUST NOT BE IN THE AUTOINDEX REGISTERS 000016 0000 000017 0000 228 229 000020 0000 GETNUM, .-. 230 000021 4032 JMS GETCH /GET A CHARACTER FROM SERIAL DISK SERVER 231 000022 7006 RTL /LEFT SHIFT 6 BITS TO BUILD UPPER HALF 232 000023 7006 RTL 233 000024 7006 RTL 234 000025 3000 DCA TEMP /SAVE UPPER 6 BITS 235 000026 4032 JMS GETCH /GET A CHARACTER FROM SERIAL DISK SERVER 236 000027 1000 TAD TEMP /BUILD 12 BIT WORD 237 000030 3030 DCA . /THIS WILL OVERWRITE ITSELF WITH JMP I GETNUM 238 / THE FIRST TIME THROUGH IT WILL GO BACK AND HARMLESSLY REPATCH 239 240 / THIS NEXT LOCATION WILL BE INCREMENTED IMMEDIATELY AFTER IT LOADS. 241 000031 5003 JMP PATCH-1 /WHEN THIS OVERWRITES THE DCA AT BOOT1 THE 242 /BOOT 2 LOADER STARTS 243 244 NOPUNCH 245 *.-2 /ALLOW FOR THE CORRECT OVERLAP 246 / THE FOLLOWING IS THE PORTION THAT GETS TOGGLED IN CALLED BOOT 1 247 / THE ODD ORDERING OF THE STORE AND ITS INCREMENT ARE SO THAT THE FIRST 248 / RTR CAN BE PATCHED TO A JMP I GETCH AND BECOME A SUBROUTINE FOR BOOT 2. 249 / THERE NEED TO BE TWO INSTRUCTIONS BEFORE THE SKSF SO THERE IS ROOM FOR 250 / THE JMP PATCH OVERWRITE AND THE RETURN ADDRESS FOR GETCH. THE JMP 251 / PATCH IS NEEDED TO BE USED TWICE SO WE CANT LET IT GET DESTROYED BY 252 / THE JMS TO GETCH. 253 254 /BEGINNING OF HAND TOGGLED CODE 255 000030 6416 GO, STLS /SEND A ZERO TO WAKE UP THE SERVER FOR BOOTING 256 000031 3000 BOOT1, DCA 0 /STORE ADDRESS. MODIFIED BY THE ISZ THAT FOLLOWS 257 000032 2031 GETCH, ISZ .-1 /BUMP STORE ADDRESS 258 000033 6401 SKSF /SKIP IF SERVER HAS SENT US A CHARACTER 259 000034 5033 JMP .-1 /WAIT FOR A CHARACTER 260 000035 6406 SKRB /READ THE CHARACTER 261 000036 7012 PTCHME, RTR /MOVE BITS INTO POSITION 262 000037 7010 RAR 263 000040 5031 JMP BOOT1 /GO DO NEXT ONE 264 /END OF HAND TOGGLED CODE 265 266 / THIS CODE IS FOR BOOT 3 WHICH IS LOADED BY THE SERVER USING BOOT 2. 267 / IT IS CAPABLE OF LOADING BLOCKS OF DATA INTO ANY FIELD. 268 000041 4020 BOOT3, JMS GETNUM /GET THE STARTING ADDRESS FROM THE SERVER 269 000042 3002 DCA STRADR /SAVE IN STRADR 270 000043 4020 JMS GETNUM /GET THE WORD COUNT FROM THE SERVER 271 000044 3001 DCA WC /SAVE IN WC. 272 000045 4020 JMS GETNUM /FETCH THE CDF TO SPECIFY THE FIELD 273 000046 3047 DCA NEWDF /PUT IT INLINE 274 000047 0000 NEWDF, .-. /WILL BE A CDF 275 000050 4020 BT3LP, JMS GETNUM /GET A DATA WORD 276 000051 3402 DCA I STRADR /PUT IT IN MEMORY 277 000052 2002 ISZ STRADR /BUMP ADDRESS 278 000053 7000 NOP /IN CASE IT SKIPS 279 000054 2001 ISZ WC /SKIP IF DONE 280 000055 5050 JMP BT3LP /GO DO ANOTHER 281 000056 5041 JMP BOOT3 /LOOP FOREVER 282 283 ENPUNCH 284 $ BOOT1 0031 BOOT2 0010 BOOT3 0041 BT3LP 0050 GETCH 0032 GETNUM 0020 GO 0030 unreferenced JPATCH 0003 NEWDF 0047 PATCH 0004 PTCHME 0036 SKRB 6406 SKSF 6401 STLS 6416 STRADR 0002 TEMP 0000 WC 0001