/SERIAL DISK BOOT / /VER 1.0 20210209 / / WRITTEN BY DOUG INGRAHAM FEB 4TH THROUGH 9TH OF 2021. / / SPECIAL THANKS TO KYLE OWEN AND VINCE SLYNGSTAD. TO KYLE FOR / MENTIONING THE HELP LOADER. I DON'T KNOW THAT I WOULD HAVE WORKED ON / THIS WITHOUT HIS PROMPTING. VINCE LOOKED OVER THE CODE SEVERAL TIMES / FINDING BUGS AND MAKING SUGGESTIONS THAT GREATLY AIDED THE PROCESS. I / HAD ALMOST GIVEN UP UNTIL HE POINTED OUT THAT I COULD INSERT A / JMP I GETCH IN THE BOOT 1 CODE REMNANT FROM BOOT 2 AND CALL THAT TO / READ CHARACTERS FROM THE SERVER. THIS SAVED JUST ENOUGH SPACE TO MAKE / IT POSSIBLE. / / THIS BOOT LOADER IS THE SHORTEST TOGGLE IN SEQUENCE KNOWN FOR NON DATA / BREAK DEVICES. IT IS INTENDED TO BE USED WITH AN 8 BIT INTERFACE LIKE / A SERIAL PORT. IT IS BASED ON THE TECHNIQUES FOUND IN THE DEC HELP / LOADER. IT ENDS UP BEING A THREE STAGE BOOT WHERE EACH STAGE REMOVES / SOME LIMITATIONS IMPOSED BY THE PREVIOUS STAGE. THE GOAL IS TO / REQUIRE THE LEAST AMOUNT OF SWITCH FLIPPING IN ORDER TO LOAD A PROGRAM / OR BRING UP AN OPERATING SYSTEM LIKE OS/8. / THE BOOT 1 PROGRAM: / / SENDS A 0 TO THE SERVER AS A WAKEUP CODE. / THEN WAITS FOR A SERIES OF 8 BIT CODES WHICH ARE CONVERTED INTO 12 BIT / INSTRUCTIONS THAT ARE PLACED INTO SUCCESIVE MEMORY LOCATIONS STARTING / WITH ADDRESS 0001. THIS CONTINUES UNTIL THE FIRST INSTRUCTION OF THE / BOOT 1 PROGRAM'S MAIN LOOP IS OVERWRITTEN BY A JMP TO THE START OF THE / BOOT 2 PROGRAM. EXECUTION THEN CONTINUES WITH THE BOOT 2 PROGRAM. / / THE 8 BIT HELP CODES SENT ARE CONVERTED TO 12 BIT INSTRUCTIONS WHICH / HAVE SOME SEVERE LIMITATIONS ON THE CODE BOOT 1 LOADS. / * MEMORY REFERENCE INSTRUCTIONS CAN ONLY DIRECTLY ADDRESS MEMORY FROM / 000 THROUGH 037. NO INDIRECT OR CURRENT PAGE REFERENCES! / * IOT'S CAN ONLY ADDRESS DEVICE CODES 0 THROUGH 3. / * FOR THE OPERATE INSTRUCTIONS YOU CAN ONLY GENERATE GROUP 1 AND NOT / ALL ENCODINGS CAN BE USED. CML, RAR, RAL, RTR, RTL, AND IAC ARE / ALLOWED. YOU CAN'T SPECIFY CLA, CLL, OR CMA OPERATIONS. / FORTUNATELY THIS STILL LEAVES A LOT OF POSSIBILITIES BUT YOU ARE / BASICALLY LIMITED TO THE BOTTOM 32 WORDS OF MEMORY AND NO INDIRECTION / WHICH ALSO MEANS NO SUBROUTINES BECAUSE THE RETURN REQUIRES / INDIRECTION. / THE BOOT 2 PROGRAM: / THE BOOT 2 PROGRAM REQUIRES INDIRECTION IN 3 PLACES. WHEN IT STARTS / IT DOES NOT HAVE ANY DUE TO THE LIMITATIONS OF THE HELP LOADER. TO / MAKE MATTERS WORSE IT CANNOT EVEN RECEIVE CODES FROM THE SERVER. THIS / IS DUE TO THE LIMITATIONS ON THE IOT DEVICE CODES THAT THE HELP LOADER / CAN GENERATE. THE FIRST ORDER OF BUSINESS IS TO TALK TO THE SERVER / WHICH WILL ALLOW THE BOOT 2 CODE TO PATCH ITSELF. THERE IS A THREE / INSTRUCTION SEQUENCE IN THE BOOT 1 CODE WHICH WAITS FOR A CHARACTER / FROM THE SERVER. A JMP I TO THE CORRECT PLACE AT THE CORRECT PLACE / WILL TURN THOSE 3 INSTRUCTIONS INTO A SUBROUTINE WHICH THE BOOT 2 CODE / CAN CALL. THE 4 INSTRUCTIONS STARTING AT PATCH BUILD THE JMP I GETCH / INSTRUCTION AND INSTALL IT AT THE CORRECT LOCATION IN THE OLD BOOT 1. / PATCH CODE NEEDS THE LINK TO BE LEFT CLEAR BY BOOT1 WHEN IT EXITS BUT / THIS SHOULD BE THE NORMAL SITUATION. THE OTHER 2 LOCATIONS REQUIRING / A PATCH TO ALLOW INDIRECTION WILL SELF PATCH THE FIRST TIME THEY ARE / ENCOUNTERED. THE FIRST OF THESE IS THE RETURN IN THE GETNUM / SUBROUTINE. THE PLACEHOLDER FOR THE JMP I GETNUM IS A DCA . WHICH / WILL OVERWRITE ITSELF WITH THE VALUE SENT BY THE SERVER. IN THIS / FIRST CALL IT WONT BE ABLE TO RETURN BUT THE JMP PATCH THAT FOLLOWS IT / WILL BE TAKEN AND A HARMLESS REPATCH WILL TAKE PLACE. THE LAST / INDIRECT REFERENCE IS FOUND IN THE BOOT2 LOOP AND IS THE INSTRUCTION / THAT WILL STORE THE WORD AT STRADR. IT TOO IS A DCA . BEFORE IT SELF / PATCHES TO A DCA I STRADR INSTRUCTION. AFTER THIS BOOT 2 IS READY TO / ACCEPT ADDRESS/DATA PAIRS AND LOAD UP THE BOOT 3 INSTRUCTIONS. WHEN / ALL THE BOOT 3 INSTRUCTIONS ARE RECEIVED THE SERVER WILL OVERWRITE THE / JMP AT THE END OF THE BOOT2 LOOP WITH A JMP TO THE BOOT 3 ENTRY POINT. / BOOT 2 IS NOT ABLE TO WRITE TO ANYTHING BUT FIELD 0 AND SENDING THE / ADDRESS/DATA PAIRS IS ABOUT HALF AS FAST AS DOING A BLOCK TRANSFER. / FOR THESE TWO REASONS THE ONLY THING BOOT 2 IS USED FOR IS TO LOAD THE / MORE CAPABLE LOADER CALLED BOOT 3. / THE BOOT 3 PROGRAM: / BOOT 3 IS PASSED THREE ARGUMENTS FOLLOWED BY A VARIABLE NUMBER OF DATA / WORDS THAT WILL BE COPIED INTO MEMORY. / ARG1 IS THE STARTING ADDRESS. / ARG2 IS THE TWO'S COMPLEMENT OF THE WORD COUNT WHERE 0 IS 4096. / ARG3 IS AN INSTRUCTION THAT IS IMMEDIATLY EXECUTED. THE INTENTION FOR / THIS IS TO ALLOW THE DATA TO BE WRITTEN TO OTHER FIELDS. IN THAT CASE / THE INSTRUCTION WILL BE A CDF. THE OTHER COMMON USE WILL BE TO / TRANSFER CONTROL TO SOME PROGRAM JUST LOADED. IN THAT CASE THIS WILL / MOST LIKELY BE A JMP I STRADR WHICH WILL JMP TO THE ADDRESS LOADED IN ARG1. / THE THREE COMMON CODES ARE: / CDF 00 6201 SELECT FIELD 0 / CDF 10 6211 SELECT FIELD 1 / JMP I 2 5402 JMP TO ARG1 THE WORD COUNT IS IGNORED. / WHAT IS EXPECTED OF THE SERVER: / THE BOOT 1 CODE WILL SEND A 000 TO THE SERVER TO INDICATE BOOT. / THE SERVER WILL SEND THE HELPER CODE FOR BOOT 2 AS FOLLOWS: / ADR HLP INST / 01 000 0000 / 02 004 0000 / 03 326 5032 / 04 327 7032 / 05 127 7012 / 06 034 1003 / 07 361 3036 / 10 206 4020 / 11 021 3002 / 12 206 4020 / 13 135 3013 / 14 102 5010 / 15 000 0000 / 16 000 0000 / 17 000 0000 / 20 000 0000 / 21 326 4032 / 22 067 7006 / 23 067 7006 / 24 067 7006 / 25 001 3000 / 26 326 4032 / 27 004 1000 / 30 305 3030 / 31 032 5003 / Gets incremented after it is loaded / -- 000 0000 / Gets loaded in AC prior to executing JMP PATCH / THE ABOVE TABLE IS THE ADDRESS, THE HELP CODE THE SERVER SENDS AND THE / INSTRUCTION THAT WILL GO IN MEMORY AFTER THE BOOT 1 CONVERSION. / THE LAST HELPER CODE SENT ABOVE WILL BE A JMP TO THE BOOT 2 LOADER. / THIS JMP OVERWRITE THE FIRST INSTRUCTION IN THE BOOT 1 MAIN LOOP WHICH / WILL CAUSE CONTROL TO PASS TO BOOT 2. / THEN THE SERVER WILL SEND A 5420 (JMP I GETNUM) TO PATCH IN THE RETURN / FOR GETNUM. / BOOT 2 IS NOT YET COMPLETELY PATCHED SO A WORD WILL NEED TO BE SENT / THAT WILL BE STORED IN STRADR BUT NOT USED. / THEN THE SERVER WILL SEND A 3402 (DCA I STRADR) TO PATCH IN THE / INDIRECT STORE IN THE MAIN LOOP. / THE BOOT 2 CODE IS NOW UP AND RUNNING. / THE SERVER CAN NOW SEND THE BOOT 3 LOADER AND FORCE A JMP TO IT. / HERE IS THE CODE FOR THE BOOT 3 LOADER SENT AS PAIRS: / 0041 4020 / 0042 3002 / 0043 4020 / 0044 3001 / 0045 4020 / 0046 3047 / 0047 0000 / 0050 4020 / 0051 3402 / 0052 2002 / 0053 2001 / 0054 5050 / 0055 5041 / NEXT WE NEED TO TRANSFER CONTROL TO ADDRESS 0041 WHICH IS THE START OF / THE BOOT 3 LOADER. / 0014 5041 / NOW BOOT 3 IS RUNNING. IN ORDER TO BOOT OS/8 THE SERVER NEEDS TO READ / THE BOOT BLOCK AND MAKE TWO CALLS TO BOOT 3 TO LOAD THE RESIDENT / PORTIONS OF OS/8. THE FIRST BLOCK WILL BEGIN AT WORD 0047 OF THE BOOT / BLOCK AND BE WRITTEN TO FIELD 1 STARTING AT 7647 AND CONSIST OF 0131 / WORDS (TWO'S COMPLEMENT IS 7647). / ARG1 WILL BE 7647. / ARG2 WILL BE 7647. / ARG3 WILL BE 6211. / THE NEXT 89 WORDS SENT WILL BE FROM THE BOOT BLOCK STARTING AT 0047. / THE SECOND CALL TO BOOT 3 WILL TRANSFER THE OTHER 2ND HALF OF THE BOOT / BLOCK TO FIELD 0 STARTING AT 7600. / ARG1 WILL BE 7600. / ARG2 WILL BE 7600. / ARG3 WILL BE 6201. / THE NEXT 128 WORDS SENT WILL BE FROM THE BOOT BLOCK STARTING AT 0200. / THE FINAL CALL TO BOOT 3 WILL BE TO EFFECT A TRANSFER OF CONTROL TO THE OS/8 ENTRY POINT AT 7605. / ARG1 WILL BE 7605. (ADDRESS OF OS/8 ENTRY POINT) / ARG2 WILL BE 0000. (DOESN'T ACTUALLY MATTER AS IT IS NOT USED.) / ARG3 WILL BE 5402. (JMP I STRADR AND OS/8 SHOULD START) / A WORD ABOUT THE .-. CONSTRUCT. / I SAW THIS IN SOME CODE I WAS READING A VERY LONG TIME AGO AND DECIDED / TO USE IT LIKE THEY WERE. AS A PLACEHOLDER FOR SELF MODIFYING CODE OR / THE RETURN ADDRESS LOCATION OF A SUBROUTINE. IT STANDS OUT FROM THE / TEXT AROUND IT SO IT CATCHES YOUR EYE AND YOU KNOW SOMETHING / INTERESTING IS HAPPENING HERE. THE CALCULATION IS CURRENT ADDRESS / MINUS CURRENT ADDRESS WHICH IS ZERO. / DEFINE THE IOT INSTRUCTIONS SKSF=6401 SKRB=6406 STLS=6416 *0000 TEMP, .-. /UPPER HALF OF 12 BITS GETS STORED HERE WC, .-. /WORD COUNT FOR BLOCK TRANSFER STRADR, .-. /ADDRESS WHERE DATA WILL BE STORED / FIRST WE MAKE A GET CHARACTER SUBROUTINE OUT OF THE BOOT 1 CODE BY / CREATING A JMP I GETCH TO PERFORM THE RETURN. JPATCH, JMP GETCH /CONSTANT FOR PATCHING PATCH, /THE LAST HELPER CODE MUST LEAVE THE LINK CLEAR! CML RTR /GENERATE A 0400 WHICH IS THE INDIRECT BIT RTR TAD JPATCH DCA PTCHME /NOW GETCH IS A CHAR FETCH SUBROUTINE. / THIS IS THE MAIN LOOP OF BOOT 2. IT ACCEPTS PAIRS OF WORDS. THE / FIRST IS THE ADDRESS WHERE THE SECOND WILL BE STORED. IT CAN ONLY / WRITE TO FIELD 0. THE FIRST TIME THROUGH THE 1ST WORD RECEIVED WILL / BE STORED IN STRADR BUT WILL NOT BE USED. THE 2ND WORD SENT WILL NEED / TO BE THE VALUE FOR DCA I STRADR (3402). THE DCA . WILL OVERWRITE / ITSELF WITH THE DCA I STRADR INSTRUCTION. THE BOOT2 PROGRAM IS NOW / COMPLETELY PATCHED. FOR PERFORMANCE REASONS IT SHOULD BE USED TO LOAD / THE BOOT3 PROGRAM. CONTROL IS EASILY TRANSFERED BY OVERWRITING THE / JMP BOOT2 AT ADDRESS 0014 WITH A JMP BOOT3 (5041) INSTRUCTION. BOOT2, JMS GETNUM /FETCH A 12 BIT VALUE DCA STRADR /SAVE THE STORE ADDRESS JMS GETNUM /FETCH ANOTHER 12 BIT VALUE DCA . /THIS GETS PATCHED TO A DCA I STRADR /WHICH STORES THE VALUE AT STRADR JMP BOOT2 /DO THE NEXT ONE ZBLOCK 0020-. /GETNUM MUST NOT BE IN THE AUTOINDEX REGISTERS GETNUM, .-. JMS GETCH /GET A CHARACTER FROM SERIAL DISK SERVER RTL /LEFT SHIFT 6 BITS TO BUILD UPPER HALF RTL RTL DCA TEMP /SAVE UPPER 6 BITS JMS GETCH /GET A CHARACTER FROM SERIAL DISK SERVER TAD TEMP /BUILD 12 BIT WORD DCA . /THIS WILL OVERWRITE ITSELF WITH JMP I GETNUM / THE FIRST TIME THROUGH IT WILL GO BACK AND HARMLESSLY REPATCH / THIS NEXT LOCATION WILL BE INCREMENTED IMMEDIATELY AFTER IT LOADS. JMP PATCH-1 /WHEN THIS OVERWRITES THE DCA AT BOOT1 THE /BOOT 2 LOADER STARTS NOPUNCH *.-2 /ALLOW FOR THE CORRECT OVERLAP / THE FOLLOWING IS THE PORTION THAT GETS TOGGLED IN CALLED BOOT 1 / THE ODD ORDERING OF THE STORE AND ITS INCREMENT ARE SO THAT THE FIRST / RTR CAN BE PATCHED TO A JMP I GETCH AND BECOME A SUBROUTINE FOR BOOT 2. / THERE NEED TO BE TWO INSTRUCTIONS BEFORE THE SKSF SO THERE IS ROOM FOR / THE JMP PATCH OVERWRITE AND THE RETURN ADDRESS FOR GETCH. THE JMP / PATCH IS NEEDED TO BE USED TWICE SO WE CANT LET IT GET DESTROYED BY / THE JMS TO GETCH. /BEGINNING OF HAND TOGGLED CODE GO, STLS /SEND A ZERO TO WAKE UP THE SERVER FOR BOOTING BOOT1, DCA 0 /STORE ADDRESS. MODIFIED BY THE ISZ THAT FOLLOWS GETCH, ISZ .-1 /BUMP STORE ADDRESS SKSF /SKIP IF SERVER HAS SENT US A CHARACTER JMP .-1 /WAIT FOR A CHARACTER SKRB /READ THE CHARACTER PTCHME, RTR /MOVE BITS INTO POSITION RAR JMP BOOT1 /GO DO NEXT ONE /END OF HAND TOGGLED CODE / THIS CODE IS FOR BOOT 3 WHICH IS LOADED BY THE SERVER USING BOOT 2. / IT IS CAPABLE OF LOADING BLOCKS OF DATA INTO ANY FIELD. BOOT3, JMS GETNUM /GET THE STARTING ADDRESS FROM THE SERVER DCA STRADR /SAVE IN STRADR JMS GETNUM /GET THE WORD COUNT FROM THE SERVER DCA WC /SAVE IN WC. JMS GETNUM /FETCH THE CDF TO SPECIFY THE FIELD DCA NEWDF /PUT IT INLINE NEWDF, .-. /WILL BE A CDF BT3LP, JMS GETNUM /GET A DATA WORD DCA I STRADR /PUT IT IN MEMORY ISZ STRADR /BUMP ADDRESS NOP /IN CASE IT SKIPS ISZ WC /SKIP IF DONE JMP BT3LP /GO DO ANOTHER JMP BOOT3 /LOOP FOREVER ENPUNCH $