sys7.1-doc-wip/OS/StartMgr/Boot3.a

2956 lines
128 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; Hacks to match MacOS (most recent first):
;
; <Sys7.1> 8/3/92 Elliot make this change
; 9/2/94 SuperMario ROM source dump (header preserved below)
;
;
; File: Boot3.a (formerly BootCode.a)
;
; Contains: boot code for the Macintosh system
;
; This code lives in the 'boot' 3 resource in the System file.
;
; This code takes over the boot process from Boot2.a, and takes it
; up to the launch of the Process Manager. This code used to be in
; Boot2.a itself but was split off during the implementation of the
; CPU Gibbly mechanism. All code which handles booting should be added to
; this file; Boot2.a doesnt do much beyond finding a CPU Gibbly with
; this code and passing on the boot baton. This code, unlike Boot2.a,
; can be in ROM if we so choose.
;
; This contains all the code necessary to get from boot to the Process Mgr.
; It also contains the code that was formerly in INIT 31 that loads INIT resources
; from INIT, RDEV, and cdev files.
;
; Written by: Darin Adler, based on old boot blocks and StartBoot.a
;
; Copyright: © 1990-1993 by Apple Computer, Inc. All rights reserved.
;
; Change History (most recent first):
;
; <SM9> 10/29/92 SWC Changed ShutdownEqu.a->Shutdown.a.
; <41> 8/13/92 JDR Offset to CloseTheFile was out of range in ForTheFuture.
; <40> 8/13/92 DTY #1039434 <BBM>: Dont register components from QuickTime if
; were booting on a 68000.
; <39> 7/22/92 csd #1018711: If script extensions cant be found in the Extensions
; folder, change <26> added a check for the System Folder. On
; Install 1 disks, though, we dont even have that; everything is
; at the root. So well also check there. This is required so WSI
; and WSII systems can have Install 1 disks.
; <38> 6/27/92 DTY #1033818: We decided to leave the Gibbly the current resource
; map after all, so CurMap needs to be changed to SysMap before
; LoadDSAT can be called.
; <37> 6/24/92 DTY #1033818 <csd>: Undo <17> since 'boot' 2 now puts the Gibbly
; underneath the system resource map before heading into 'boot' 3
; so that the system will now always be the top resource map.
; <36> 6/15/92 csd #1032429 <gbm>: Added the file type 'vbnd' to the list of types
; from which INITs are run. These are Telephone Tools from the
; Comm Toolbox Telephone Manager.
; <35> 5/28/92 DTY #1030972: After 'DSAT' 0 is set up, look at a bit in low memory
; to see if 'boot' 2 could find a Gibbly or not. If it couldnt,
; the bit is set, which means that this code should bring up the
; error alert saying that the disk is too old.
; <34> 4/29/92 DTY #1027105: Roll out changes from <27>. The script extensions were
; being loaded, but seconary inits, like Akiko and
; InputBackSupport were still being disabled since theyre just
; normal INITs. Making them work would take a lot of hacking
; around, and that doesnt give us a nice general solution anyway,
; so just dont try to fix the problem at all.
; <33> 4/23/92 DTY Fix a bug in the linked patch extension mechanism. (I TOLD you
; it wasnt tested.) Set up D5 with a pointer to the linked patch
; loader so that linked patch extensions will work.
; <32> 4/20/92 DTY #1024149: Dont prevent DAL from loading if AppleTalk is off.
; <31> 4/20/92 JSM Moved this file from BootCode.a to Boot3.a, keeping all
; revisions.
; <30> 4/17/92 DTY Add mechanism to load linked patch files from the Extensions
; folder. Conditionalized for theFuture. No, I didnt test this
; change. I dont have an 'lpch' file to test with. And its not
; theFuture yet.
; <29> 4/16/92 DTY Always include ResourceMgrPriv.a (in case this file is used for
; a Gibbly), and dont include LAPEqu.a any more, since the dummy
; LAP routine went away.
; <28> 4/15/92 JSM Roll-in changes from SuperMario to support their ROM gibbly,
; should not change System build. Take out some leftover revision
; <28> comments from when part of this file lived in
; StartSystem.a.
; <27> 4/13/92 DTY #1027105,<csd>: Script extensions should be considered part of
; required system software, and should not be disabled when the
; shift key is held down if Roman is not the primary script.
; Also, removed changes from revision <12>, AppleTalk does the
; right thing now.
; <26> 4/2/92 csd #1018711,<FM>: Change the LoadINITFilesInFolder routine to look
; in the System Folder if theres an error trying to get the
; Extensions Folder when loading script extensions.
; <25> 4/2/92 DTY #1025555,<BBM>: When this file was part of StartSystem.a,
; MakeSysHeapGrowable was done way early in the boot process. It
; even does it twice. My worries about doing this so early in the
; last change are therefore unfounded. Move the first call to
; MakeSystemHeapGrowable back to StartSystem.a so that Gibblies do
; not get closed out. Get rid of the check around the second
; MakeSystemHeapGrowable.
; <24> 4/1/92 DTY #1025555,<FM>: Add A/UX support.
; <23> 3/27/92 DTY #1025567: Call _RsrcZoneInit before growing the system heap for
; the Process Manager to blow away any resources in the
; application heap that will get trashed by the call to
; _SetAppBase.
; <22> 3/26/92 DTY #1024282,<gbm>: I took the MoveHHi out of LinkedPatchLoader, so
; we dont need to keep so much stack space in memory all the
; time. Go back to the way it was before <19>.
; <21> 3/25/92 FM last checkin was #1025326
; <20> 3/25/92 FM Rolled in code from StartSystem.a. Now StartSystem.a only
; contains code to load a gibbly. BootCode.a (the gibbly) now
; takes care of all startup initialization.
; <19> 3/20/92 DTY BLT: Since the linked patch loader now calls _MoveHHi, VM is
; hanging with a double bus fault because the stack pointer is
; being moved to a paged out page again. Bump up the stack size
; needed for boot.
; <18> 3/16/92 DTY #1024540: Load 'pext' (El Kabong printing extensions) files from
; our special folders.
; <17> 3/3/92 DTY #1023670: The system 'boot' 3 needs to call _UseResFile before
; loading linked patches. This is because MacsBug resets CurMap to
; be the reference number of TopMapHndl, which could be a Gibbly
; calling the systems boot code. This causes the linked patch
; loader to fail since it might not find any 'lpch' resources in
; the Gibbly.
; <16> 2/18/92 DTY Use d5 as a flag meaning that we had to implement StripAddress
; ourselves. If we had to relocate the boot code, check this flag
; to determine if we patched StripAddress. This lets Scruffy
; work.
; <15> 2/11/92 DTY Release the 'lodr' resource after linked patches have been
; loaded. This frees up about 2K in the system heap.
; <14> 2/11/92 DCL Changed the name of include file TSMEqu.[aph] to
; TextServices.[aph] for better read-ability.
; <13> 1/23/92 csd Make sure that enough pages are in memory before we move the
; supervisor stack pointer when relocating the boot world. If a
; stack operation causes a page fault, it creates a double bus
; fault, guaranteed.
; <12> 1/19/92 DTY Add a bunch of skanky code to prevent network code from being
; loaded if AppleTalk is turned off: Set up a fake LAP manager,
; and dont load DAL, AppleShare, or FileShare. (And just think
; about how 7 Up had to do this without changing the boot code!)
; Also get rid of NewROMCheck since this is done implicitly by the
; Gibblies.
; <11> 1/17/92 DTY Dont set up StkLowPt when relocating the boot world. Setting it
; causes the stack sniffer to fire.
; <10> 1/14/92 csd If VM adds memory the machine, relocate the boot world (code,
; stack, globals) to the new MemTop/2 area. This is because the VM
; code costs memory in the System heap, and CubeE no longer has
; room to boot on a 2 megabyte machine. Also, move the BootGlobals
; record and other equates to BootEqu.a so we dont have to keep
; the StartSystem.a and BootCode.a versions in sync.
; <9> 12/12/91 csd #1017421: with bal, loading the components from the QuickTime
; init because it wont since the Component Manager is implemented
; already. Load components from the System file before we load
; init files. This doesnt work yet because the component manager
; cant handle 'thng' resources which come from a resource file
; with the refnum 0, which is what HomeResFile returns for the
; System.
; <8> 12/10/91 JH Oops, forgot to fill out the script language record before
; sending it to SetTextServiceLanguage.
; <7> 12/9/91 JH Added a little subroutine called TellTSMScriptAndLanguage. It
; gets called right after _AddScriptFonts and its purpose is to
; tell the text service manager what the system script and
; language is.
; <6> 11/23/91 YK Removed RegisterComponetFile calls. Added ComponentSearch at the
; end of LoadINITFiles.
; <5> 11/15/91 DTY Change the resource ID of the 'lodr' resource to match the ones
; in the Gibbly ERS.
; <4> 11/12/91 DTY Pass off a pointer to the 'ptbl' resource to the linked patch
; loader. Change type of linked patch load resource to 'lodr'.
; <3> 11/11/91 DTY The linked patch loader has been moved to the 'pldr' 0 resource
; for CPU Gibblies. Get this resource and jump to it instead of
; importing the label and jsring.
; <2> 11/8/91 DTY Adding a comment describing why this file is here.
; <1> 11/8/91 DTY first checked in
;
; Change history from StartSystem.a:
;
; <56> 11/4/91 YK Register components in the INIT loading loop.
; <55> 11/4/91 JSM Take out SysPrivateEqu.a again.
; <54> 10/28/91 SAM Added a default define of false to has3rdFloppy.
; <53> 10/28/91 SAM/KSM Rolled in Regatta file:
; On Spike with caches diabled, we patch the MFM WrData vector of
; the Sony driver so we can use an updated timing constant in the
; Write code. The original constant is *barely* within spec and
; with caches disable it is no longer even close.
; Changed CheckFor040CacheInhibit to use the hwPriv call to push
; the caches, added a clock rate calculation to determine the
; amount of adjustment TimeDBRA will require with the caches off
; on the differently clocked 040s. Added a Terror2 (ROM minor
; version 17) check to the Zap PRAM routine so it will work on
; Zydeco.
; Updated the kNo040CacheTimeDBRA value.
; Slam a slower/lower TimeDBRA when the 040 caches are inhibited.
; (jmp) Make the System cmd-opt-r-p PRAM Reset work on TERROR
; machines to fix a TERROR bug.
; Changed HighestSupportedBoxFlag to Eclipse33.
; Added code to inhibit the 68040 caches if the high bit of the
; MMFlags byte is set (PRAM 8A).
; Add back the check for Gestalt after loading VM cuz if VM does
; not load, Gestalt is not yet implemented on non IIci ROM
; machines.
; Adding free memory checks after VM loads.
; Removed the previous revision -- Macsbug has been fixed to load
; in copyback!
; Inhibited all 040 caches while loading Macsbug cuz its too
; brain-damaged to load in copyback.
; <52> 9/16/91 JSM Cleanup header, dont include SysPrivateEqu.a (already in dump
; file).
; <51> 7/2/91 JSM Remove obsolete 7.0 related SysVers conditionals.
; <50> 6/12/91 LN added #include 'InternalOnlyEqu.a'
; <49> 6/11/91 gbm Take out conditional for Regatta
; <48> 4/13/91 stb dty, BRC#86692: Replace WhichCPU (borrowed from ROM) with
; HandleMacIIWith030. Now handle exactly one case where we help
; accelerators be VM-capable.
; <47> 4/2/91 SAM Bumping HighestSupportedBoxFlag for Regatta build.
; <46> 3/31/91 csd dba: Changed the test for 040 in the WhichCPU routine so that it
; doesnt jam 0 into the CACR, thereby possibly nuking any data
; which has not been flushed out of the cache.
; <45> 3/13/91 stb bbm, #83253: setup and use new ExpandMem global
; emMinSysHeapFreeSpace which specifies how much elbow room to
; leave in the system/process mgr heaps.
; <44> 2/19/91 gbm csd, #Go5 approved: Make sure _MemoryDispatch is NOT implemented
; on machines without PMMUs. Also fix the related bug in the ci
; ROM that sets MMUType wrong.
; <43> 2/15/91 gbm stb & dba, BRC # 82829: Fix the WhichCPU routine so that is
; stops turning off data cache and data bursting on '030s
; <42> 2/11/91 stb gbm, WS #stb211: change BSR.S back to BSR so MacsBug wont die
; if you bail during install (by holding down the mouse button).
; Disassembler, too.
; <41> 2/11/91 stb gbm, BRC # 82423: implement StripAddress early enough to use
; when installing VM
; <40> 1/29/91 csd stb, Whiteboard Bug: Moved the SetDefaults code to an earlier
; position so that it executes before code that uses the
; variables.
; <39> 1/23/91 stb TED,81551: test a result code before BCCing.
; <38> 1/19/91 stb & DC (& dfh for some of it) change 'dbex' id; adjust file cache
; allowance; coordinate upward and downward growth limits.
; <37> 1/14/91 stb & mda; more net booting stuff; disable extension disabling if
; desired; do DoWeHaveEnoughRAMToBoot earlier; give file cache a
; little less BufPtr room. add culprit names for VM, Debugger,
; Disassembler; jam CPUflag to support 3rd-party processors for
; VM.
; <36> 12/18/90 stb & JDR; add error check after _MemoryDispatch.
; fix infinite loop in MakeSysFree if couldnt get desired amount.
; <35> 12/15/90 stb & KSM; move the currently-executing filename to avoid conflict
; with INITs which check CurApName to see if its post-boot time.
; Replace error 106 with 25. Remove _MemoryDispatch declaration.
; <34> 12/13/90 stb & gbm; no longer load AppleTalk from a file.
; Use source to GetDefaultStartup to avoid problem on Plus.
; Reserve 100K for post-boot allocations by Process Mgr & Finder.
; <33> 12/12/90 stb & gbm; pass bufPtrLimit to LoadFileSystemCache code
; & dba; added 'appe' (background app) to the list of boot-executables.
; & bbm; add Cmd-Option-pr to reset PRAM on Plus, SE, II, Portable
; & k s; add net booting hooks
; <32> 11/15/90 stb & JDR; move dsBufPtrTooLow to SysErr.a
; <31> 11/9/90 dba & JSM; move 8•24 GC loading before script system loading
; <30> 11/1/90 dba & stb; some misc. cleanup; fix bug where we were checking
; against the wrong value for the barrier; fix obscure error
; handling bug in NewPtrStartup; add NewPtrStartup for post-boot
; that returns an error; add an ellipsis on the end of long file
; names, instead of relying on smart code in the DSAT; put in the
; file name for all files opened outside the system file, not just
; for files with INIT resources
; <29> 10/31/90 dba & csd; add code to load the 8•24 GC support code
; <28> 10/30/90 stb & BBM; make booting safer and more predictable in low-memory
; conditions.
; <27> 10/22/90 JJ Rex V8: Change all box flag references to use boxMacLC. Get rid
; of boxElsie and boxElsieV8.
; <26> 10/1/90 dba add innocuous value for location 0
; <25> 9/25/90 SAM Bumped highestBoxFlag to ElsieV8.
; <24> 9/22/90 gbm (with dba) change the routines that could kill ApplZone so that
; they do InitApplZone to get rid of the old contents
; <23> 9/16/90 gbm Fix detatching of system INITs. I don't think it ever worked...
; <22> 9/10/90 dba fix name copy bug
; <21> 8/27/90 VL (actually dba) set TheZone to SysZone when doing
; MakeSystemHeapGrowable since the application heap goes away.
; <20> 8/10/90 dba load A/ROSE and AppleTalk; this obsoletes INIT 18 and prevents
; the need for INIT 16
; <19> 8/6/90 stb add test for at least 1.5MB to make sure we can boot 7.0
; <18> 7/20/90 dba get rid of PTCH -1
; <17> 6/22/90 dba (with emt) move this code onto the stack to avoid fragmenting
; the system heap
; <16> 6/11/90 EMT Moved alternate trap dispatcher loading from patch files.
; <15> 5/29/90 DDG NEEDED FOR SIXPACK: Changed all the sixpack conditionals from
; six-point-oh-seven to six-point-oh-six.
; <14> 5/11/90 PKE NEEDED FOR SIXPACK: if this file is used for 6.0.6:
; Conditionalized early loading of script systems (see <9> and
; <13>) on SysVers >= $700. ALSO (for 7.0 only): Added call to new
; Script Mgr _AddScriptFonts routine after all INITs.
; <13> 5/5/90 PKE Added call to Script Mgr _InitScripts (new) after script system
; installation.
; <12> 4/25/90 dba change MMU check in LoadVM section (also add feature to load
; MacsBug before VM)
; <11> 4/20/90 dba check to see that the Shift key is the only key held down for
; Extensions Disabled
; <10> 4/20/90 dba close QD port much earlier; it isnt doing anyone any good; do
; InitApplZone for each INIT file; rely on patch to SetAppBase to
; do InitApplZones
; <9> 4/19/90 dba add support for Script Systems; increase system heap size
; <8> 4/19/90 dba make StartupScreens and Disable Extensions work
; <7> 4/18/90 dba change bsr.s to bsr (I will never check in w/o building)
; <6> 4/18/90 dba change branch from pl to mi to fix MakeSysFree bug (INITs were
; not being loaded); restuff dirID to make setting of the noINITs
; bit work right
; <5> 4/17/90 dba fix bug with InitApplZone stuff
; <4> 4/16/90 csd save registers around calls to ptch and PTCH resources since
; they dont obey the register saving conventions.
; <3> 4/11/90 dba put dynamic system heap size code for the Plus and SE back here;
; do InitApplZone before each INIT, instead of after each
; MakeSysFree; detach ourselves so we can support remote booting
; closing the System file and opening a new one
; <2> 4/10/90 dba fix bugs in MakeSysFree (wrong register d2 vs. d0 and possible
; error where size is odd)
; <1> 4/9/90 dba new today
;
; Change History from data fork of System file:
;
; <5> 3/22/90 dba change name of LoadPatch to LoadLinkedPatches
; <4> 3/21/90 dba take out the lingering Debugger statement
; <3> 3/21/90 dba change to work with new boot blocks for 7.0
; <2> 12/28/89 dba use MAIN instead of PROC to get dead code stripping; also get
; rid of wierd header that was required by a strange build rule in
; the old Make file; a corresponding change was made in
; SysObj.Make
; <1.5> 11/17/89 dba got rid of checks for 64K ROMs
; <1.4> 10/14/89 EMT Always load in RAM cache in system 7.
; <1.3> 6/5/89 EMT One more try.
; <1.2> 6/2/89 EMT Fixed coding errors in 1.1.
; <1.1> 6/1/89 EMT Removed ROM69 stuff. Bootstrap StripAddress if it doesnt exist.
; Use StripAddress before executing 'PTCH's.
; <1.0> 11/16/88 CCH Added to EASE.
; <S174> 4/10/87 bbm Save off the A5 world for the inits. (Some inits relied on
; CurrentA5 to be set up.)
; <S145> 3/27/87 bbm The algorithm that S115 used to grow the heap was to enlarge the
; heap by 16k or the size of the patch - whichever was bigger.
; What you really want is 16k free in addition to the size of the
; patch.
; <S128> 3/23/87 JTC On 64K ROMs be sure not to use nonexistent traps (such as
; SizeRsrc) or resize heap (since boot blocks are loaded at 64K).
; <S115> 3/19/87 JTC Ensure sufficient sys heap space before loading patches, using
; SizeResource to figure the local min. Then guarantee MinSysExtra
; space after loading last one. Code borrowed from INIT=31.
; <S109> 3/18/87 bbm Added the code for PTCH $FFFF. This enables general patches
; for all machines before the patches are read in by PTCH 0 and
; general patches after the patches are read in by PTCH $FFFF.
; <S108> 3/17/87 bbm For system heaps larger than 58k, rom69patch needed to move the
; boot code (the boot code is loaded in at $10000). Since the boot
; code has moved, the return address on the stack should be
; modified. If you change the nature of the stack — which rom69fix
; depends on - you must also modify rom69fix.a.
; <P029> 1/22/87 JTC JTC The above dates should surely be 86 and the res type is now
; 'PTCH', despite the above comments. This change is to
; accommodate the new PTCH=0 patch file for all systems.
; 11/20/86 BB Changed resource type for patch files from 'PTCH' to 'ptch'.
; 11/15/86 BB New today.
;
; Change History from INIT 31:
;
; <2> 2/19/90 sad <version 5>
; look into Extensions and Control Panels folders using Folder
; Mgr; use 1-deep resource calls instead of 64K ROM-compatible
; hacks; got rid of d7 hack for 64K ROMs; assures MinSysFree after
; last INIT file instead of before first
; <1.4> 11/17/89 dba got rid of checks for 64K ROMs
; <1.3> 6/19/89 CCH Removed check for files of type 'mntr' from version 1.2.
; <1.2> 2/21/89 CCH Added 'mntr' type to list of files that contain INITs.
; <1.1> 1/17/89 CCH Merged changes from 6.0.3.
; <1.0> 11/16/88 CCH Added to EASE.
; <S424> 3/15/88 DBG Prevent invisible INIT files from running
; <S393> 2/12/88 JRM Use fndrInfo bit to eliminate extra OpenResFiles. Set the bit if
; no INIT resources are found for a file. Check the bit before
; calling OpenResFile
; <SB293> 10/2/87 DAF Added an InitGraf before the InitPalettes so that all gDevices
; will be active.
; <S285> 9/21/87 DAF Changed the ROM85 test in s277 to test MacII or greater, rather
; than equal.
; <S277> 9/16/87 DAF Added InitPalettes here before INIT files are loaded. This
; causes the data structures to be allocated early rather than
; during the first init that calls _InitWindows.
; <S173> 4/10/87 JTC Fix CDEV to be cdev.
; <S114> 3/19/87 JTC Fix to get 16K min in sys heap even if no RDEV,INIT,CDEV files.
; Also, look for CDEV files too.
; <S9> 2/14/87 JTC Call InitApplZone after SetApplBase to get initialation
; attendant thereto.
; <S6> 1/5/87 JTC Add new resource 'sysz' comprising just one long word to request
; said amount of system heap space. Put code into inner loop of
; loading and executing INITs below to guarantee #MinSysExtra
; (borrowed from start code) free space at every execution.
; 8/4/86 DLD Converted source to MPW.
;
; System 3.1
;
; 2/8/86 JTC&LAK Fixed bug in patching return address into boot blocks after the
; boot blocks have been moved. Also added a BCLR to assure that
; the half-way point in memory is even after the DIV by 2.
; 2/5/86 LAK Fixed bug for Shuffle: return address needs to be updated after
; stack move.
;
; for InfoSphere
;
; 1/7/86 LAK On old ROMs: if not called from $10000 space or BufPtr has been
; moved below MemTop/2 + 1K already then punt the normalization.
; Someone has probably already 'normalized' the world, hopefully
; correctly.
;
; System Tools Disk for Plus
;
; 12/10/85 LAK Modified to look for files of both INIT and RDEV types.
; 12/6/85 ELR New Today
;
; ——————————————————————————————————————————————————————————————————————————————————————————————————
; equates
supportsMFM equ 1
If &type('has3rdFloppy') = 'UNDEFINED' Then
has3rdFloppy: equ 0
EndIf
load 'StandardEqu.d'
include 'MMUEqu.a'
include 'BootEqu.a'
include 'EgretEqu.a' ; <15>
include 'Folders.a'
include 'GestaltEqu.a' ; <33>
include 'HardwarePrivateEqu.a' ; just for hwCbAUX
include 'LinkedPatchMacros.a' ; For kROMVersion equates <10>
include 'ReliabilityEqu.a' ; just for RelPRAM <33>
include 'ResourceMgrPriv.a' ; for SetupResourceFileAttributes & Resource Override traps <28> <29>
include 'ScriptPriv.a' ; <13>
include 'ShutDown.a' ; just for _SDRestart <33><SM9>
include 'SonyEqu.a' ; <11>
include 'TextServices.a' ; so we have SetTextServiceLanguage <14>
include 'UniversalEqu.a' ; <15>
MACHINE MC68040
_AUXDispatch opword $ABF9 ; <24> A/UXs trap dispatch *** move to Traps.a
auxSecondaryInit equ 36 ; <24> Parameter for _AUXDispatch
auxExtraDebuggerSize equ $1c00-debuggerGlobalSize ; <24> Amount of additional storage space required by A/UX for MacsBug
bFInvisible equ 7 ; bit in ilFlUsrWds+fdFlags which means an invisible file
bFNoINIT equ 7 ; bit in ilFlUsrWds+fdFlags+1 which means no INIT resources
vmDebugSignature equ 'JB' ; magic number to debug VM
bbVMDebugSignature equ bbPageFlags ; boot blocks offset of magic word to debug VM
kNo040CacheTimeDBRA25MHz equ 1560 ; # of DBRA's per ms with 25MHz 040 caches inhibited <8>
kNo040CacheTimeDBRA33MHz equ 1513 ; # of DBRA's per ms with 33MHz 040 caches inhibited <9>
k040CyclesPerDBRA equ 4 ; # of cycles it takes an 040 to execute a DBRA <9>
kNoCacheWriteAdj equ $30EA ; No Caches Write Delay constant <11>
kBootStackSizeNeeded equ $2000 ; this many bytes of stack should be in physical memory <12> <19> <22>
kNetBootNameID equ -16507 ; name of NetBoot file <33>
kNetBootProcID equ -16507 ; id of the net boot proc resource <33>
kNetBootDriverRefNum equ -50 ; refnum if we are to load the net booter <33>
kAROSENameID equ -16501 ; name of A/ROSE file
kAppleTalkNameID equ -16500 ; name of AppleTalk file
k8Dot24GCNameID equ -16454 ; name of 8•24 GC file <29>
kLinkedPatchFileID equ 'lpch' ; <30> File type containing a bunch of 'lpch' resources.
kPatchLoaderResourceType equ 'lodr' ; Resource type containing linked patch loader
kPatchLoaderResourceID equ -16385 ; Resource ID of resource containing linked patch loader
kPatchTableResourceType equ 'ptbl' ; Resource type containing patch table ranges
kFileShareCreator equ 'hhgg' ; <12>
kAppleShareCreator equ 'afps' ; <12>
kDALCreator equ 'dald' ; <12>
BootCode MAIN
; Registers passed in from boot blocks:
; A3 = handle to this resource
; A4 = dirID of the startup application (for pre-7.0 systems; used by the remote booting INIT)
; A5 = pointer to globals (SP + 400)
; A6 = pointer to boot blocks (used by the remote booting INIT)
move.l a3,a0 ; get the size of this boot code
_GetHandleSize
lea @continue,a0 ; copy from @continue to the end of the boot code
lea BootCode,a1
sub.l a0,a1 ; get BootCode-@continue
add.l a1,d0 ; fix up size
sub.l d0,sp ; make room on the stack
move.l sp,a1 ; copy onto the stack
_BlockMove ; move it up
jmp (a1) ; pass control there
@continue
move.l a3,-(sp) ; get rid of the resource
_ReleaseResource ; and continue with booting as normal
move.l ROMBase,a0 ; point into a safe place in ROM
add.l #$10000,a0 ; 64K into the ROM is always safe
move.l a0,0 ; jam this nice value into location 0
move.l sp,CurStackBase ; MacsBug works better if CurStackBase is set up
; ——————————————————————————————————————————————————————————————————————————————————————————————————
SetUpStartupScreen
; Load everything we need for “Welcome to Macintosh” or a startup screen.
move.w SysMap,CurMap ; <38> Make the System the current map so the DSAT will load.
moveq #0,d0 ; load DSAT 0
bsr LoadDSAT ; get the handle
move.l d0,d6 ; stash this away to dispose later
_InitFonts ; prepare to draw some text
bsr EraseMyIcon
; ——————————————————————————————————————————————————————————————————————————————————————————————————
CheckForPreGibblySystem
; If there are no Gibblies that can boot this machine according to 'boot' 2,
; display the System Too Old version.
btst #systemEnabledBit,ExtensionsEnabledByte
beq.s @gibblyPresent
moveq #dsOldSystem,d0
_SysError
@gibblyPresent
; ——————————————————————————————————————————————————————————————————————————————————————————————————
ShowStartupScreen
; First, open the resource fork of the startup screen file to look for a 'PICT' (0) resource.
moveq #1,d7 ; no startup screen is up yet
subq #2,sp ; make room for refNum
pea BootGlobals.bootBlocks+bbScreenName(a5)
_OpenResFile ; open the file
move.w (sp)+,d0 ; get the refnum
bmi.s @noResourceFork
move.w d0,-(sp) ; push back the refNum for later closing
subq #4,sp ; make room for handle
clr.w -(sp)
_GetPicture
move.l (sp)+,d0 ; check handle
bz.s @noPICTResource
move.l d0,a2 ; save the handle for later
move.l (a2),a0 ; dereference it
move.l picFrame+botRight(a0),-(sp) ; push the pictures bounds rect
move.l picFrame+topLeft(a0),-(sp)
bsr CenterOnMainScreen ; center a rectangle on the screen
move.l a2,-(sp) ; get the picture handle
pea 4(sp) ; pass the centered rectangle
_DrawPicture
addq #8,sp ; get rid of the rectangle on the stack
moveq #0,d7 ; a startup screen has been displayed
@noPICTResource
_CloseResFile ; close the file (refNum left on stack from above)
@noResourceFork
tst.b d7 ; did we put something up there?
bz.s @done ; yes, we are done
; Now, try the data fork of the startup screen file to look for something to display on the screen.
lea BootGlobals.bootBlocks+bbScreenName(a5),a1
bsr LoadBelowBufPtr
bnz.s @noDataFork
cmp.l #342*512/8,d2 ; is the whole thing there?
blo.s @noDataFork
move.l #((342<<16)+512),-(sp) ; put a rect the size of the original Mac screen
clr.l -(sp) ; on the stack (0,0,342,512) as bounds for a bitMap
bsr CenterOnMainScreen ; center a rectangle on the screen
move.w #512/8,-(sp) ; now push the rowBytes of the bitMap
move.l a2,-(sp) ; and push the base address of the bitMap
move.l sp,-(sp) ; srcBits is here
pea BootGlobals.port+portBits(a5) ; dstBits is the screen
pea 8+bounds(sp) ; srcRect and dstRect is the one we computed
move.l (sp),-(sp)
clr.w -(sp) ; srcCopy mode
clr.l -(sp) ; no maskRgn
bsr EraseMyIcon
_CopyBits
lea bitMapRec(sp),sp ; get rid of our bitMap on the stack
moveq #0,d7 ; a startup screen has been displayed
bra.s @done
@noDataFork
; Now, do the welcome screen.
bsr EraseMyIcon
moveq #dsGreeting,d0 ; put up the greeting
_SysError
@done
IF NOT forROM THEN
; ——————————————————————————————————————————————————————————————————————————————————————————————————
UnimplementedTrap EQU $9F
MemoryDispatchTrap EQU $5C
GestaltTrap EQU $AD
SetUpCPUFlag
; HandleMacIIWith030 decides whether the processor is an 030 with MacII ROMs.
; We put it here so that 030 accelerator boards can work where the
; ROM doesn't know how to check for them. We ignore 040's because either the ROM must know about
; them or the vendor is doing some hardware magic to make it work without our help.
bsr HandleMacIIWith030 ; <48>
FixMMUTypeAndKillMemoryDispatch
; The ci ROM has a bug in 32-bit mode which causes MMUType to be set to $FF. So, if MMUType
; is $FF, we set it to the right thing. _MemoryDispatch is mistakenly implemented
; in 32-bit mode on machines where there is no MMU (because of the previous bug....).
; So, for machines without an MMU, well unimplement the call.
; NOTE: The MMUType that we set here is a "best guess", since checking for PMMU vs. HMMU at
; this point is hard to do. We're assuming that accelerator makers will either:
; have this set up correctly before we get here, or set it up correctly later on.
tst.b MMUType ; check if MMUType has been setup
bpl.s @keepAGoin ; if it's positive, it has been
clr.l d0 ; <48>
move.b CPUFlag,d0 ; <48>
lea @DefaultMMUTypes, a0 ; point to our table of defaults
move.b (a0, d0.w), MMUType ; get the default type of MMU
cmp.b #cpu68030, d0 ; are we at least on an '030?
bge.s @keepAGoin ; yes, then assume MemoryDispatch is okay to have around
move.w #UnimplementedTrap, d0 ; no, then set MemoryDispatch be the same as
_GetTrapAddress ; the Unimplemented trap.
move.w #MemoryDispatchTrap, d0
_SetTrapAddress newOS
bra.s @keepAGoin
@DefaultMMUTypes
dc.b NoMMU ; 68000 - no MMU
dc.b NoMMU ; 68010 - no MMU
dc.b HMMU ; 68020 - HMMU (but could be 68851... oh well)
dc.b PMMU030 ; 68030 - '030 MMU
dc.b PMMU040 ; 68040 - '040 MMU
align
@keepAGoin
ENDIF ; NOT forROM
;————————————————————————————————————————————————————————————————————————————————————————————————————
; CheckFor040CacheInhibit - If we're on an 040 machine and bit 7 of MMFlags (PRAM byte 8A) is set
; then inhibit the caches (can you say sssloooowwww?) and update TimeDBRA
; according to a calculated Clock rate (25 or 33Mhz currently). <SAM>
CheckFor040CacheInhibit ; <5> SAM
CMPI.B #cpu68040,cpuFlag ; Are we on an 040?
BNE.S @Continue ; -> Nope, do nothing
BTST.B #7,MMFlags ; Check the inhibit all caches bit in MMFlags
BEQ.S @Continue ; -> Leave them enabled
_FlushInstructionCache ; Push both caches back to RAM (FlushICache will do both caches) <10>
MOVEC CACR,D0 ; Get the CAcheControlRegister
AND.L #~((1<<CACR_DE_040)|(1<<CACR_IE_040)),D0 ; Create a mask excluding the DE & IE bits
MOVEC D0,CACR ; Clear DE & IE in the CACR (caches are now inhibited)
MOVEQ #0,D0 ; Clear D0 <10>
MOVE.W TimeDBRA,D0 ; Get TimeDBRA <10>
DIVU.W #(1000/k040CyclesPerDBRA),D0 ; Compute the clock rate based on TimeDBRA & k040CyclesPerDBRA <10>
CMPI.W #28,D0 ; Pick a value between 25 & 33 <10>
BLS.S @Slam25 ; -> 25 MHz <10>
@Slam33 MOVE.W #kNo040CacheTimeDBRA33MHz,D0 ; Get the 33Mhz constant <10>
BRA.S @SetIt ; -> Set it
@Slam25 MOVE.W #kNo040CacheTimeDBRA25MHz,D0 ; Get the 25Mhz constant <10>
@SetIt MOVE.W D0,TimeDBRA ; Stuff the value
IF NOT forROM THEN ; Do not install this patch when this file is being <28>
; built as a ROM gibbly, the ROM is fixed. <28>
CMPI.B #boxQuadra700,boxFlag ; Are we on a Spike? (Quadra 700) <11><61>
BNE.S @Continue ; -> No. Do not install patch to MFMWrData <11>
LEA EndCachesOffMFMPatch,A0 ; Point to the end of the Patch <11>
LEA CachesOffMFMPatch,A1 ; Load the "Caches are off, fix the floppy MFM write code" patch <11>
MOVE.L A0,D0 ; Make a copy of the patch's starting address <11>
SUB.L A1,D0 ; Calc the size of the Floppy patch <11>
MOVE.L D0,D3 ; Copy the size to D3 <11>
_NewPtr ,Sys ; Get a block of Sys Heap memory <11>
BNE.S @Continue ; -> No mem. Exit <11>
EXG.L A0,A1 ; Swap src w/dest
MOVE.L D3,D0 ; Size
_BlockMove
MOVE.L A1,jMWrData ; Install the patch in the sony Write Data vector <11>
ENDIF ; <28>
@Continue
; ——————————————————————————————————————————————————————————————————————————————————————————————————
; Install the new dispatcher for systems that need it.
import InstallDispatch
jsr InstallDispatch
;——————————————————————————————————————————————————————————————————————————————————————————————————
CheckForExtensionsDisabled
; If the Shift key is held down, disable loading of all Extensions, including VM and INITs,
; and background applications, and Finder Startup Folder.
; Do not allow disabling if a 'dbex' resource is not present. This allows users to ensure that
; their INITs will run (e.g. security packages). <37>
clr.b ResLoad ; no preloads please
subq #4,sp ; make room for function result
move.l #'dbex',-(sp) ; if present, allow user to Disable Extensions
move.w #-16385,-(sp) ; 'dbex' (-16385)
_GetResource
st ResLoad ; restore resLoad to proper state
move.l (sp)+,d0 ; did we get a handle?
bz.s @dontDisable ; no, user wont get to disable
move.l d0,-(sp) ; get rid of the empty handle
_ReleaseResource
movem.l KeyMap,d0-d3 ; get four words worth of keys
bclr #7,d3 ; clear off the power key
bclr #1,d1 ; clear off the Caps Lock key
bclr #0,d1 ; clear off and test the Shift key
bz.s @dontDisable ; Shift key not held down, dont disable extensions
or.l d1,d0 ; stray keys held down?
or.l d2,d0
or.l d3,d0
bnz.s @dontDisable ; yes, dont disable extensions
bclr #extensionsEnabledBit,ExtensionsEnabledByte ; disable extensions
moveq #dsExtensionsDisabled,d0
bsr BootAlert ; put up an alert if we should
@dontDisable
;___________________________________________________________________________
ResetPRAM
; CheckForResetPRAM: Checks for the Cmd-Option-R-P keys down, and Resets PRAM <33>
; if they are down.
;
; Only do this if were on a Plus ($0075), SE ($0276), II ($0178), or Portable ($037A).
; Reset the extended parameter RAM by invalidating the validity longword.
;
; TERROR ROM note: There is a bug in the TERROR ROM where the cmd-opt-r-p sequence <7> jmp
; sometimes doesnt work (a register is being trashed). So, to rectify this problem,
; we go ahead and let the reset fly on TERROR ROM machines even though they are
; IIci overpatches. This problem seems to be most accute on Spikes, so we may
; be able to restrict this code to Spikes only. Still investigating.
;
; *** TO DO:
; reset mouse speed in original PRAM to medium speed on all machines
; Keymaps locations for Cmd-Opt-P-R
; Cmd = $37 => bit .15 of D1
; Opt = $3A => bit .2 of D1
; P = $23 => bit .27 of D1
; R = $F => bit .23 of D0
clr.w BootGlobals.resetFlag(a5) ; by default, dont reboot
movem.l KeyMap,d0-d3 ; get four words worth of keys
; clear off keys which might be down but we dont care about
bclr.l #7,d3 ; clear off the power key
bclr.l #1,d1 ; clear off the Caps Lock key
; test for the keys we do care about, clearing them as we test
; test for only Cmd, Option, and P, taking care of all tests on D1.
eori.l #(1<<15)+(1<<2)+(1<<27),d1
bne @noReset
; the only bit left set should be the R bit, so well change it,
; and then OR everything together, and reset PRAM only if
; everything is clear.
bchg.l #23,d0 ; change the R key bit
or.l d2,d0 ; OR together everything thats left
or.l d3,d0
bnz.s @noReset ; something else is down, dont reset PRAM
; now check to see if were on a ROM which needs resetting help
movea.l ROMBase,a0
move.w 8(a0),d2
cmp.w #kROMVersionPlus,d2
beq.s @resetPRAM
cmp.w #kROMVersionSE,d2
beq.s @resetPRAM
cmp.w #kROMVersionII,d2
beq.s @resetPRAM
cmp.w #kROMVersionPortable,d2
beq.s @resetPRAM ; <7> jmp
cmp.w #kROMVersionIIci,d2 ; <7> jmp
beq.s @chkMinorVers ; <7> jmp
bra.s @noReset ; <7> jmp
@chkMinorVers ; <7> jmp
move.b 18(A0),d2 ; <7> jmp
cmp.b #kROMMinorTERROR,d2 ; <7> jmp
beq.s @resetPRAM ; <7> jmp
cmp.b #kROMMinorTERROR2,d2 ; <9> SAM
beq.s @resetPRAM ; <9> SAM
bra.s @noReset ; <7> jmp
@resetPRAM ; stolen from StartInit.a
lea @stuff,a1 ; stuff to write into PRAM
subq.w #RelPram>>16,sp ; allocate buffer on stack
movea.l sp,a0 ; get buffer ptr
move.l #RelPram,d0 ; get #, addr PRAM bytes
_ReadXPram ; read the reliability MGR info
movea.l a1,a0 ; point to table data
move.l (a0)+,d0 ; get PRAM len/addr, point to data
_WriteXPRam ; kill the extended PRAM signature
lea SysParam,a0 ; standard PRAM buffer address
moveq.l #-1,d0 ; mask/data to write
move.b d0,(a0) ; kill the signature in the buffer
_WriteParam ; write the buffer to PRAM
_InitUtil ; Init PRAM
movea.l sp,a0 ; get buffer ptr
move.l #RelPram,d0 ; get #, addr PRAM bytes
_WriteXPram ; restore the reliability MGR info
move.w #-1,BootGlobals.resetFlag(a5)
bra.s @continue
@stuff
dc.l $0004000C ; XPRAM signature len/addr
dc.l 'Gone' ; invalidate XPRam signature with this
@noReset
@continue
; ——————————————————————————————————————————————————————————————————————————————————————————————————
RememberPhysicalMemTop
; Prior to loading VM, MemTop holds the top of physical memory.
; Well use this later for our reality checking.
move.l MemTop,BootGlobals.physicalMemTop(a5)
; ——————————————————————————————————————————————————————————————————————————————————————————————————
DoWeHaveEnoughRAMToBoot
; Weve got to have at least minRAMNeeded to get 7.0 on its feet. minRAMNeeded was chosen
; for just enough to get Finder up with room for one control panel. Moved earlier in <37> to crash
; before VM or MacsBug soaks up too much memory.
cmpi.l #minRAMNeededToBoot,BootGlobals.physicalMemTop(a5) ; is RAM big enough?
bhs.s @weHaveEnough
moveq #dsNotEnoughRAMToBoot,d0
_SysError
@weHaveEnough
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadTemporaryStripAddress
; Patch loading depends on StripAddress, so install a temporary version for the time before loading.
; moved earlier in <41>
; This must get stomped by anyone who installs a _real_ StripAddress later.
moveq #0,d5 ; <16> Assume we dont patch _StripAddress
moveq #$55,d0 ; check if StripAddress is already implemented
_GetTrapAddress newOS
MOVE.L A0,D1 ; save its address
MOVE.W #$9F,D0 ; get unimplemented trap address
_GetTrapAddress newTool
CMP.L A0,D1 ; are they the same?
BNE.S @done ; yes, it already is implemented
moveq #$55,d0
LEA TemporaryStripAddress,a0
_SetTrapAddress newOS ; StripAddress doesnt exist, use mine as a bootstrap
moveq #1,d5 ; <16> Use D5 to mean we patched _StripAddress. Any number will do…
@done
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadVMAndDebugger
; Load VM and MacsBug, but do it in a different order if Joes debugging signature is found.
btst #extensionsEnabledBit,ExtensionsEnabledByte
bz.s @done ; extensions disabled means VM and MacsBug are disabled
cmp.w #vmDebugSignature,BootGlobals.bootBlocks+bbVMDebugSignature(a5)
beq.s @forDebugging ; if it is set right, do debugging
@normal
bsr LoadVM ; VM first
bsr LoadDebugger
bra.s @done
@forDebugging
bsr LoadDebugger ; debugger first; well crash for sure (well, not for sure...)
bsr LoadVM
@done
; ——————————————————————————————————————————————————————————————————————————————————————————————————
ChooseBufPtrLimit ; <33>
; If VM loaded, _MemoryDispatch with D0 = -4 will return any limit to BufPtr that VM knows about.
; This might be NuBus™ slots or ROM in the logical RAM space (as on the IIci in 24bit mode).
; Put any VM limit to bufPtrs descent into BootGlobals.bufPtrLimit(a5) (replacing the default).
GetBufPtrLimit equ -4 ; MemoryDispatch selector to get any bufPtr limit
move #GestaltTrap,d0 ; no ROM Gestalt means no MMU (Plus, SE, II?)
_GetTrapAddress newOS
move.l a0,d1
move #UnimplementedTrap,d0
_GetTrapAddress newTool
cmp.l a0,d1
beq.s @noVMLimit
move.l #gestaltVMAttr,d0 ; is VM on?
_Gestalt ;
tst.w d0
bne.s @noVMLimit ; if there was an error, forget it
move.l a0,d0
btst #gestaltVMPresent,d0
beq.s @noVMLimit ; if VM isnt present, then leave
move.w #GetBufPtrLimit,d0
_MemoryDispatch ; if no limit, leave it set to the default
tst.l d0
ble.s @noVMLimit ; if error, skip out. if zero, VM knows no limit
move.l BootGlobals.bufPtrLimit(a5),d1
cmp.l d0,d1 ; VMs limit < default?
bhi.s @noVMLimit ; if so, stick with the default.
move.l d0,BootGlobals.bufPtrLimit(a5)
@noVMLimit
; ——————————————————————————————————————————————————————————————————————————————————————————————————
bsr AdjustBarrier ; go take other things into account <38>
; ——————————————————————————————————————————————————————————————————————————————————————————————————
RememberLogicalMemTop
; After loading VM, MemTop holds the top of logical memory.
move.l MemTop,BootGlobals.logicalMemTop(a5)
; ——————————————————————————————————————————————————————————————————————————————————————————————————
CleanUpBootPort
; Clean up the port that QD sets up for booting.
pea BootGlobals.port(a5) ; close the port used for booting
_ClosePort
; ——————————————————————————————————————————————————————————————————————————————————————————————————
RelocateBootWorld
; If VM has added memory to the machine, relocate all the boot stuff to the new MemTop/2 <10>
; note: we ignore the QuickDraw globals in the BootGlobals record <10>
move.l BootGlobals.logicalMemTop(a5), d0 ; starting MemTop <10>
cmp.l BootGlobals.physicalMemTop(a5), d0 ; did we add memory? <10>
bls.s LoadUserAlerts ; if not, dont bother <10>
lsr.l #1, d0 ; new MemTop/2 <10>
move.l d0, a1 ; point to the new stack <10>
; Make sure that the pages where the stack will be are in physical memory. We want about 12K <12>
; fo the stack, so use the logical page size to figure out how many pages to bring in. <12>
move.l #gestaltLogicalPageSize, d0 ; we want the page size <12>
_Gestalt ; VM implements Gestalt <12>
bne.s LoadUserAlerts ; huh? just bail… <12>
move.l #kBootStackSizeNeeded, d1 ; size of stack needed <12>
move.w a0, d0 ; page size <12>
divu d0, d1 ; number of pages we need <12>
move.l a1, a0 ; where the stack will be <12>
@makePhysicalStackLoop
tst.b (a0) ; bring a page in <12>
sub.w d0, a0 ; point to previous page <12>
dbra d1, @makePhysicalStackLoop ; do enough pages <12>
move.l a1, sp ; move the stack <10>
lea BootGlobals.initialSP(a5), a0 ; old globals <10>
move.l #BootGlobals.size, d0 ; size of globals <10>
_BlockMove ; relocate the globals <10>
lea BootGlobals.initialA5-BootGlobals.initialSP(a1), a5 ; point A5 into the new globals <10>
lea BootGlobals.initialA6(a5), a6 ; fix A6 <10>
lea FinishMovingBootWorld, a0 ; start of code to move <10>
lea EndOfBootCode, a1 ; end of code to move <10>
sub.l a0, a1 ; how much code to move <10>
move.l a1, d0 ; number of bytes to move <10>
sub.l d0, sp ; move the stack down to make room <10>
move.l sp, a1 ; destination is above the stack <10>
_BlockMove ; move the rest of this code <10>
move.l sp, CurStackBase ; a new beginning for the stack <10>
move.l sp, a0 ; current stack <10>
sub.l DefltStack, a0 ; leave room for the stack <10>
_SetApplLimit ; give the System Heap room to grow <10>
lea BootGlobals.lowestBufPtr(a5), a0 ; new minimum BufPtr default <10>
cmp.l BootGlobals.bufPtrLimit(a5), a0 ; is the limit already higher than this? <10>
bls.s @bootCodeMoved ; if so, dont need to worry <10>
move.l a0, BootGlobals.bufPtrLimit(a5) ; bump lower limit past new globals <10>
@bootCodeMoved ; <10>
jmp (sp) ; go to new code location <10>
FinishMovingBootWorld ; <10>
tst.w d5 ; <16> Check our _StripAddress semaphore
bz.s @done ; <16> If D5 is not set, we didnt patch _StripAddress
moveq #$55, d0 ; <10>
lea TemporaryStripAddress, a0 ; <10>
_SetTrapAddress newOS ; retarget the interim StripAddress code <10>
@done ; <10>
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadUserAlerts
; Now that we have done all the boot message stuff, go on to the user alerts.
moveq #2,d0 ; load DSAT 2
bsr LoadDSAT ; get the handle
move.l d0,-(sp) ; now let the Resource Mgr. forget
_DetachResource
move.l d6,-(sp) ; and get rid of DSAT 0
_ReleaseResource
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadTemporaryNewPtrStartup
; INITs depend on NewPtrStartup, so install a temporary version for the time before loading.
move.w #$9C,d0
LEA TemporaryNewPtrStartup,a0
_SetTrapAddress newOS ; NewPtrStartup doesnt exist, use mine as a bootstrap
; Create a block containing the NewPtrStartup that will be used after boot. <30>
; It will be installed at the end of the boot below, just before starting the Process Mgr.
lea JustReturnAnError,a1 ; get the start in a1
lea JustReturnAnErrorEnd,a2
sub.l a1,a2 ; calculate the size in a2
move.l a2,d0 ; put the size in d0
_NewPtr sys ; make a block for this code
bne BadSystem
exg a0,a1 ; copy from the old block into the new
move.l a2,d0 ; put the size in d0
_BlockMove
move.l a1,BootGlobals.postBootNewPtrStartup(a5)
; ——————————————————————————————————————————————————————————————————————————————————————————————————
MakeBootDriveWDRefNum
; Up until now, BootDrive contained a drive number; make it a WDRefNum (the current volume).
lea BootGlobals.paramBlock(a5),a0
clr.l ioFileName(A0) ; we dont want the name
_GetVol ; make BootDrive a VRefNum/WDRefNum
move.w ioVRefNum(A0),BootDrive
ActivateTrackCache
; Turn on the track caching of the Sony driver.
btst.b #hwCbAUX,HWCfgFlags ; are we under A/UX?
bnz.s @noSonyDriver
MOVE.W #dskRfn,ioRefNum(a0) ; refNum of the Sony driver
MOVE.W #9,csCode(a0) ; disk cache control code
MOVE.W #$FF01,csParam(a0) ; install and enable
_Control ; allocate and install track cache
@noSonyDriver
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadFileSystemCache
; This makes assumptions about the RAM cache that are not true of the 6.X cache:
; • The 'ptch' (41) resource must have the system heap and locked bits set.
; • The cache locals are allocated by the cache code.
; • The cache code is aware that it is not loaded above BufPtr and allocates its own buffer space.
; • The cache code is aware that the limit to bufPtr is passed in d2.
; This reserves 32K for other things which also need BufPtr space to get the machine booted
; (e.g. AppleShare).
bsr AdjustBarrier ; <38>
btst #extensionsEnabledBit,ExtensionsEnabledByte ; <38>
bne.s @normal ; extensions disabled means feed him a small limit <38>
move.l BufPtr,d2 ; survival-mode, get my machine booted! <38>
sub.l #$10000,d2 ; give the cache 64K <38>
bra.s @continue ; <38>
@normal
move.l BootGlobals.bufPtrLimit(a5),d2 ; <33>
add.l #elbowRoomCacheCantHave,d2 ; <38>
@continue
moveq #41,d0
bsr LoadLowerCaseptch
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadPTCHZero
MOVEQ #0,D0 ; load patches for all ROMs
BSR LoadPTCH
; ——————————————————————————————————————————————————————————————————————————————————————————————————
; Set the ExpandMem global emMinSysHeapFreeSpace <45>
move.l ExpandMem,a0
move.l #minSysHeapFreeSpace,d0
move.l d0,ExpandMemRec.emMinSysHeapFreeSpace(a0)
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadPTCHROMSpecific
; *** obsolete, get rid of this eventually
MOVEA.L ROMBase,a0 ; ID = ROM version number
MOVE.W 8(A0),D0 ; load ROM-specific patch
BSR LoadPTCH
LoadLinkedPatches
lea LinkedPatchName,a0
move.l a0,CurNamePtr ; Put ptr to the VM string <37>
subq #4,sp
move.l #kPatchTableResourceType,-(sp)
clr.w -(sp)
_GetResource
move.l (sp),d0 ; <15> Keep 'ptbl' on stack to save a call to _RecoverHandle
bz.s @noPatchTable
move.l d0,a0
_HLock ; Lock it down
move.l (a0),a3 ; Pass the pointer to the patch loader in A3
subq #4,sp
move.l #kPatchLoaderResourceType,-(sp) ; 'lodr'
move.w #kPatchLoaderResourceID,-(sp)
_GetResource ; Use the Systems patch loader if the gibbly doesnt have one.
move.l (sp),d0 ; <15> Keep handle to 'lodr' on the stack for a release later
bz.s @noPatchLoader
move.l d0,a0
move.l (a0),d0
_StripAddress
move.l d0,a0
if theFuture then
move.l a0,d5 ; <33> Remember the linked patch loader address so it can be used to load linked patch extensions
endif
jsr (a0) ; Call the patch loader
if theFuture then
move.l #kLinkedPatchFileID,a2 ; <30> Get 'lpch' files
move.l #kExtensionFolderType,d7 ; <30> from the Extensions folder
bsr LoadINITFilesInFolder ; <30>
endif
_ReleaseResource ; <15> Release the linked patch loader
_ReleaseResource ; <15> Release the 'ptbl' resource
bra.s @done ; Load extensions, Process Manager, etc.
@noPatchTable
@noPatchLoader
moveq #dsBadPatch,d0 ; Couldnt find the patch loader code
_SysError
@done
; ——————————————————————————————————————————————————————————————————————————————————————————————————
bsr RealityCheck ; check for enough memory to continue
move.l #-1,CurNamePtr ; no currently-executing file
; ——————————————————————————————————————————————————————————————————————————————————————————————————
TestForNeedToReset
; Earlier we chose whether we need to reboot. On the Plus, we dont have _SDRestart until
; linked patches are loaded. Rather than move that code into this file, we simply waited.
tst.w BootGlobals.resetFlag(a5)
beq.s @skipReset
_SDRestart
@skipReset
; ——————————————————————————————————————————————————————————————————————————————————————————————————
SetupProcessMgrLaunch
; So that old code that patches Launch will still work, we point the Launch trap to the code used
; to start the Process Mgr. Later, we will call Launch, so all patches to Launch will be executed.
lea StartProcessMgr,a0 ; point to the code to start the Process Mgr.
move.w #$A9F2,d0 ; get the Launch trap number
_SetTrapAddress
; ——————————————————————————————————————————————————————————————————————————————————————————————————
Load8Dot24GC ; <31><29>
; Load 8•24 GC software from separate file in the control panels folder (or from the system file).
btst #6,ROM85 ; Color QuickDraw?
bnz.s @noCQD ; no CQD, no 8•24
move.w #k8Dot24GCNameID,d0 ; get 8•24 GC
move.l #kControlPanelFolderType,d7
move.l #'gc24',d5 ; resource ('gc24', 32)
move.w #32,d6
clr.w d3 ; clear the DontCloseOnError flag
bsr ExecuteFromSystemOrFileByName
@noCQD
; ——————————————————————————————————————————————————————————————————————————————————————————————————
bsr CreateApplicationHeap
; ——————————————————————————————————————————————————————————————————————————————————————————————————
; Secondary A/UX initializations (Pre-script systems)
btst.b #hwCbAUX,HWCfgFlags ; <24>
beq.s @notAux ; <24>
move.w #auxSecondaryInit,-(sp) ; <24>
move.l #1,-(sp) ; <24>
_AUXDispatch ; <24> Let A/UX do some initialization
@notAux ; <24>
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadScriptSystems
; Load all of the INIT resources in script systems.
; These must be loaded before anyone puts up any dialogs or such.
btst #extensionsEnabledBit,ExtensionsEnabledByte
bz.s @skipScripts
move.l #'scri',a2 ; look for these types of INITs
move.l #kExtensionFolderType,d7
bsr LoadINITFilesInFolder
@skipScripts
; Now initialize the script systems that are installed. We have to do this even if INITs
; are disabled so that Roman gets initialized.
subq #2,sp ; make room for OSErr result <13>
_InitScripts ; <13>
addq #2,sp ; ignore result for now <13>
; *** what kind of reality checking/error checking should go here?
; ——————————————————————————————————————————————————————————————————————————————————————————————————
; Secondary A/UX initializations
btst.b #hwCbAUX,HWCfgFlags ; <24>
beq.s @notAux ; <24>
move.w #auxSecondaryInit,-(sp) ; <24>
clr.l -(sp) ; <24>
_AUXDispatch ; <24> Let A/UX do some more initialization
@notAux ; <24>
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadINITResourcesInSystemFile
; Load all of the INIT resources from the System file.
;
; Note that one of these INIT resources may be the INIT 20 resource used for remote booting.
; This INIT closes the System file and opens a new system file. In addition, it returns the
; dirID of the folder containing the startup application in A4. To top that, it also clobbers
; the boot blocks at A6 with the boot blocks
moveq #-1,d4 ; refNum -1 means we load from the System file
bsr LoadINITResources ; call the common routine below
; ——————————————————————————————————————————————————————————————————————————————————————————————————
bsr MakeSystemHeapGrowable
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadAROSE
; Load A/ROSE.
btst #extensionsEnabledBit,ExtensionsEnabledByte
bz.s @skip ; extensions disabled means A/ROSE is disabled
move.w #kAROSENameID,d0 ; get A/ROSE
move.l #kExtensionFolderType,d7
bsr LoadINITFileByName
beq.s @foundInExtensionsFolder
move.w #kAROSENameID,d0 ; get A/ROSE
move.l #kSystemFolderType,d7
bsr LoadINITFileByName
@foundInExtensionsFolder
@skip
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadAppleTalk
; Load AppleTalk from System.
btst.b #hwCbAUX,HWCfgFlags ; are we under A/UX?
bnz.s @noALAP
move.l #'lmgr',d5 ; call common routine to load and execute resource <29>
clr.w d6
clr.w d3 ; clear the DontCloseOnError flag
bsr ExecuteFromSystem ; <34>
@noALAP
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadNetBoot ; <33>
; Load NetBoot.
; SDRefNum must be kNetBootDriverRefNum (-50) to continue
subq #4,sp ; Make room for parameters
move.l sp,a0 ; Point to the parameter block
; Wed like to call GetDefaultStartup, but its not on the Plus or SE, so we reimplement it. <34>
MOVE.L #$00040078,D0 ; Read 4 bytes starting at loc $78
_ReadXPRam ; Get it from PRAM.
move.l (sp)+,d0 ; put result into d0
cmp.w #kNetBootDriverRefNum,d0; refnum in low word
bne.s @skip
move.w #kNetBootNameID,d0 ; get NetBoot
move.l #kExtensionFolderType,d7
move.l #'proc',d5 ; call common routine to load and execute resource
move.w #kNetBootProcID,d6
moveq #1,d3 ; set the DontCloseOnError flag
bsr ExecuteFromSystemOrFileByName
; *** beq.s @skip ; were not actually net-booting this time
; *** subq #2,sp ; room for OSErr
; *** _ReInitScripts
@skip
; ——————————————————————————————————————————————————————————————————————————————————————————————————
bsr CreateApplicationHeap
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadSystemComponents ; <9>
; Register any components lurking in the system file <9>
btst #extensionsEnabledBit,ExtensionsEnabledByte
bz.s @skipThings
;pascal long RegisterComponentResourceFile(short resRefNum, short global) <9>
clr.l -(sp) ; return value <9>
clr.w -(sp) ; system map fref <9>
move.w #1,-(sp) ; register them globally <9>
_RegisterComponentResourceFile ; <9>
addq #4,sp ; ignore result <9>
@skipThings
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadINITFiles
; This section searches the default volume for files of type cdev, RDEV
; and INIT. When it finds one, it opens it and attempts to Get1IndResource
; on type INIT. If successful, it locks down the resource and executes the
; code within. When the code returns, it closes the file (thus throwing away
; the code if it didnt DetachResource itself), and continues with the next
; cdev/RDEV/INIT file it finds. Note that ResLoad is turned off over the
; OpenResFile call.
;
; Differences between this and the boot blocks INIT launcher:
;
; • This doesnt DetachResource before calling the INIT code (if the
; code wants to be detached, it must RecoverHandle and do it itself).
; • This assumes that the Locked bit of the INIT is set (so did the
; boot blocks, but its worth restating!).
;
; MemTop -> +-------------------+ Top RAM location
; | I/O, screen RAM |
; initial BufPtr -> +-------------------+ Top of program-usable memory
; | static allocation |
; | |
; | |
; | |
; 1K + MemTop/2 -> +-------------------+
; | boot blocks |
; MemTop/2 -> +-------------------+
; | boot stack |
; ApplLimit -> +-------------------+
; | |
; | application heap |
; ApplZone -> +-------------------+
; | |
; | system heap |
; SysZone -> +-------------------+
; | |
; | system globals |
; 0 -> +-------------------+
;
; With this, an INIT resource may grab BufPtr space down to MemTop/2 + 1K. It
; may use the application zone for temporary heap memory. It may even grow the
; system heap (preferably with the 'sysz' mechanism).
btst #extensionsEnabledBit,ExtensionsEnabledByte
bz.s @skipINITs ; extensions disabled means INITs are disabled
move.l #0,a2 ; look for all three types of INITs
move.l #kExtensionFolderType,d7
bsr LoadINITFilesInFolder
move.l #kControlPanelFolderType,d7
bsr LoadINITFilesInFolder
move.l #kSystemFolderType,d7
bsr LoadINITFilesInFolder
; ——————————————————————————————————————————————————————————————————————————————————————————————————
; Register Components from 'thng' files.
move.l #minSysHeapFreeForINIT,d5 ; minimum space needed to run an INIT <6>
bsr MakeSysFree ; resize (Is this OK for 'thng's?) <6>
moveq #34,d0 ; ComponentSearch selector <6>
_ComponentDispatch ; look for 'thng's <6>
@skipINITs
; ——————————————————————————————————————————————————————————————————————————————————————————————————
; Now that networks are usable, give script systems a chance to install fonts over the network. <14>
subq #2,sp ; make room for OSErr result
_AddScriptFonts
addq #2,sp ; ignore result for now
; *** what kind of reality checking/error checking should go here?
;------------------------------------------------------------------------------------------------
; Go tell text services manager what the system script is and what its default language is
bsr TellTSMScriptAndLanguage
; ——————————————————————————————————————————————————————————————————————————————————————————————————
; Switch from the boot-time NewPtrStartup to one that returns an error. <30>
move.l BootGlobals.postBootNewPtrStartup(a5),a0
move.w #$9C,d0
_SetTrapAddress newOS ; use the NewPtrStartup that just returns an error
; ——————————————————————————————————————————————————————————————————————————————————————————————————
; We still have two heaps. We are going to get minSysHeapFreeAfterBoot bytes, even if it
; means growing the system heap again. This time, though, well stop reserving anything,
; and take as much as we need.
_RsrcZoneInit ; <23> Call _RsrcZoneInit to blow away system resources loaded in the application heap
; Guarantee some free space after last INIT (or for folks lacking any INIT files at all).
clr.l BootGlobals.reservedForAfterBoot(a5) ; stop reserving that big chunk <34>
move.l #minSysHeapFreeAfterBoot,d5 ; what we want to have free in the system heap <34>
bsr MakeSysFree ; resize
; ——————————————————————————————————————————————————————————————————————————————————————————————————
; Now, we call the launch trap. Before INITs, we patched Launch to point here, to the code that
; is used to start the Process Mgr. Any patches to Launch will be executed, followed by the Process
; Mgr. itself.
clr.w -(sp) ; for the wierdos who look
clr.l -(sp) ; we pass the parameters like the old launch
pea #'MultiFinder' ; (rest in peace)
move.l sp,a0 ; pass those parameters
_Launch
StartProcessMgr
; The Process Mgr. is structured like an application (a bunch of code segments), but
; the code segments are numbered differently so they can be in the System file.
; First, set up the application heap, and then load the jump table for the Process Mgr.
CLR.L StkLowPt ; keep VBL task out
MOVE.L BufPtr,sp ; start stack out here
CLR.L ScrapHandle ; no need for this
_InitApplZone ; cut back the heap
SUBQ #4,SP ; make room for function result
MOVE.L #'scod',-(SP) ; <25> Keep stb happy.
MOVE.W #processMgrCode0,-(sp)
_GetResource ; load the jump table resource ('CODE', processMgrCode0)
MOVE.L (SP)+,d1 ; save away the handle for later release
bz.s BadSystem ; no, this system is damaged
; Set up A5 worlds (above and below) and the stack pointer.
MOVE.L d1,A0 ; get the handle in an address register
MOVE.L (A0),A0 ; dereference so we can get at the jump table
SUB.L (A0)+,SP ; allocate "above A5" space
MOVE.L SP,A5 ; set up A5
SUB.L (A0)+,SP ; allocate "below A5" space
MOVE.L A5,CurrentA5 ; remember A5 for the Process Mgr.
MOVE.L SP,CurStackBase ; remember stack for this one, too
MOVE.L SP,StkLowPt ; for heap-stack crashes
; Move jump table from the resource to its place below A5.
MOVE.L (A0)+,D0 ; get the jump table size
MOVE.L (A0)+,A1 ; get the load offset
MOVE.W A1,CurJTOffset ; remember the offset
ADD.L A5,A1 ; add in the base address
pea 2(A1) ; push the starting address onto the stakc
_BlockMove ; move it in
; Now that things are set up, we can release the jump table resource.
MOVE.L d1,-(SP) ; push the resource handle
_ReleaseResource ; de-allocate it
; Set up the stack limit based on how much stack the Process Mgr. needs.
MOVE.L SP,A0 ; get the stack
SUB.W #processMgrStackSize,A0 ; make space for stack
_SetApplLimit ; set the new limit
; Start the Process Mgr.
rts
; ——— THE END ———
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadDSAT
; Loads the desired DSAT resource, and install it in low-memory.
;
; D0.W -> resource ID of DSAT
; D0.L <- handle of DSAT
subq #4,sp ; room for returned handle
MOVE.L #'DSAT',-(SP)
MOVE.W D0,-(SP)
_GetResource
MOVE.L (SP)+,D0
bz.s BadSystem
move.l d0,a0
move.l (a0),DSAlertTab
RTS
BadSystem
; Come here if a resource that is required is missing.
moveq #dsBadPatch,d0
_SysError
; ——————————————————————————————————————————————————————————————————————————————————————————————————
ExecuteFromSystem ; <34>
; Execute a resource that is gotten from the system.
;
; a5 -> globals, including parameter block and file name storage
; d3.W -> DontCloseOnError flag. If nonzero, don't CloseTheFile on nonzero result
; d5.L -> resource type
; d6.W -> resource ID
moveq #-1,d4
bra.s DontOpenAFile
; ——————————————————————————————————————————————————————————————————————————————————————————————————
ExecuteFromSystemOrFileByName ; <29>
; Execute a resource that is gotten either from the system or from a special file.
;
; a5 -> globals, including parameter block and file name storage
; d0.W -> ID of STR resource containing the file name
; d3.W -> DontCloseOnError flag. If nonzero, don't CloseTheFile on nonzero result <33>
; d7.L -> folder type to look in
; d5.L -> resource type
; d6.W -> resource ID
moveq #-1,d4 ; refNum -1 means no file was opened yet
btst #extensionsEnabledBit,ExtensionsEnabledByte
bz.s DontOpenAFile ; extensions disabled means do not open the special file
bsr.s SetUpForFileByName
bne.s DontOpenAFile
bsr OpenTheFile
DontOpenAFile
move.w #mapTrue,ROMMapInsert ; get ROM as well as System file
subq #4,sp
move.l d5,-(sp)
move.w d6,-(sp)
_GetResource
move.l (sp)+,d1 ; get the result
bz.s @noResource
move.l d1,-(sp) ; save for later release
bsr ExecuteHandle
tst.w d3 ; do we care about closing the file? <33>
bz.s @continue ; nope, just release and close <33>
tst.w d0 ; yes, check for response <33>
beq.s @continue ; glad we checked, but dont close it <37>
addq #4,sp ; pop the (no longer a resource) handle <37>
rts ; leave without closing <37>
@continue
_ReleaseResource
@noResource
bsr CloseTheFile
@DontClose
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadINITFileByName
; If so, open the file, look for a 'sysz', and cycle through the INITs.
; If the system heap must be resized, then close and reopen the resource file.
;
; d0.W -> resource ID of string containing name of file to load
; a5 -> globals, including parameter block and file name storage
; d7.L -> folder type to look in, then folder dirID
;
; ccr <- Z means success, NZ means error
;
; d4.W = refnum of opened file
; d5.L = requested contiguous free space in system zone
bsr.s SetUpForFileByName
bnz.s @done
bsr LoadINITFile
@done
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
SetUpForFileByName
; Get the name of a file from a resource.
; Set up a parameter block with the appropriate values, find a folder to work in.
;
; a5 -> globals, including parameter block and file name storage
; d7.L -> folder type to look for
; d0.W -> resource ID of the files name
;
; d0.W <- error code
; d7.L <- dirID of found folder
subq #4,sp ; make room for handle result
move.w d0,-(sp) ; get that string
_GetString
move.l (sp)+,d0 ; get result
bz.s @notFound
move.l d0,a0 ; get handle
moveq #0,d0 ; clear out size for BlockMove <22>
move.l (a0),a0 ; dereference handle
move.b (a0),d0 ; get length
addq.b #1,d0 ; add one for the length byte
lea BootGlobals.fileName(a5),a1
_BlockMove
bsr SetUpForFolder ; prepare for that folder as well
@done
rts
@notFound
move.w #resNotFound,d0 ; get error code
bra.s @done
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadINITFilesInFolder
; The major file-loading loop for INITs. For each file in the folder specified by d7,
; by index, check whether its an INIT, RDEV or cdev. If so, open the file, look
; for an 'sysz', and cycle through the INITs. If the system heap must be resized,
; then must close and reopen the resource file.
;
; a5 -> globals, including parameter block and file name storage
; d7.L -> folder type to look in, then folder dirID
; a2 -> 0 means get INIT, RDEV, cdev, anything else means that file type only
;
; d3.W = index of current file
; d4.W = refnum of opened file
;
; no return values
move.l a4,-(sp) ; save a4 for folder. Used for creator type. <9>
bsr SetUpForFolder
bz.s @foundFolder ; we got it, keep going <26>
cmp.l #'scri', a2 ; looking for script extensions? <26>
bne DoneWithFolder ; if not, dont try System Folder <26>
move.l #kSystemFolderType, d7 ; try the System Folder <26>
bsr SetUpForFolder ; <26>
bz.s @foundFolder ; it worked <39>
; <39> go ahead and try anyway with 0 as a dirID in case everything is at the root
moveq #0, D7 ; try the root <39>
@foundFolder
lea BootGlobals.fileName(a5),a0 ; store pointer to files name
move.l a0,BootGlobals.paramBlock+ioFileName(a5)
clr.w BootGlobals.paramBlock+ioFileType(a5) ; "version" and permissions
moveq #0,d3 ; start looping through the files
NextFileInFolder
addq.w #1,d3 ; increment the file index
lea BootGlobals.paramBlock(a5),a0 ; point at IO block
move d3,ioFDirIndex(a0)
move.l d7,ioDirID(a0)
_HGetFileInfo ; d3 file in the folder
bnz DoneWithFolder ; no more files in the folder, stop loading
move.l ioFlUsrWds+fdType(a0),d0 ; grab file type for testing
move.l ioFlUsrWds+fdCreator(A0),a4 ; save file creator type for LoadInitFile <9>
move.l a2,d1 ; what file type are we looking for
bz.s @allTypes ; 0, means look for all boot-executable types
cmp.l d1,d0 ; is this the type were looking for?
bra.s @checkType ; go ask the storm trooper
@allTypes
cmp.l #'INIT',d0 ; is it a system extension?
bne.s @notExtension ; <12> no, keep checking
cmp.l #kFileShareCreator,a4 ; <12> Is it FileShare?
bne.s @goodFile ; <12> No, its just some extension
bra @checkAppleTalkState ; <12> See if AppleTalk is active. If not, dont load FileShare
@notExtension
cmp.l #'pext',d0 ; <18> Is it an El Kabong printing extension?
beq.s @goodFile ; <18> Yes. Go load it.
cmp.l #'cdev',d0 ; is it a control panel?
BEQ.S @goodFile ; yes, use it
cmp.l #'RDEV',d0 ; is it a Chooser extension?
bne.s @notRDEV ; <12> no, keep checking
cmp.l #kAppleShareCreator,a4 ; <12> Is it AppleShare?
bne.s @goodFile ; <12> No, its just some Chooser extension
bra @checkAppleTalkState ; <12> See if AppleTalk is active. If not, dont load AppleShare
@notRDEV
cmp.l #'cbnd',d0 ; is it a connection tool?
BEQ.S @goodFile ; yes, use it
cmp.l #'fbnd',d0 ; is it a file transfer tool?
BEQ.S @goodFile ; yes, use it
cmp.l #'tbnd',d0 ; is it a terminal emulation tool?
BEQ.S @goodFile ; yes, use it
cmp.l #'vbnd',d0 ; is it a telephone tool?
BEQ.S @goodFile ; yes, use it
cmp.l #'adev',d0 ; is it a network extension?
BEQ.S @goodFile ; yes, use it
cmp.l #'ddev',d0 ; is it a database extension?
BEQ.S @goodFile ; yes, use it
cmp.l #'appe',d0 ; is it a background app? <33>
BEQ.S @goodFile ; yes, use it
cmp.l #'fext',d0 ; is it a Finder extension?
@checkType
bne.s NextFileInFolder ; no, move along
@goodFile
btst #bFNoINIT,ioFlUsrWds+fdFlags+1(a0) ; do we know there are no INIT resources?
bne.s NextFileInFolder ; yes, skip slow OpenResFile
btst #bFInvisible,ioFlUsrWds+fdFlags(a0) ; is it invisible?
bnz.s NextFileInFolder ; yes, skip it, since it may be evil
if theFuture then
cmp.l #kLinkedPatchFileID,d1 ; <30> Is this a file with type 'lpch'?
bne.s @normalINITFile ; <30> No. Assume it has 'INIT' resources
bsr.s LoadLinkedPatchFile ; <30> Go load linked patches from this file
bra.s NextFileInFolder ; <30> Go around for another one.
endif
@normalINITFile ; <30>
bsr.s LoadINITFile ; load all the INITs from the file
bnz.s NextFileInFolder
; Check to see if we actually found any INITs in this file. If we didnt, then save this useful
; information as a fndrInfo bit so we can skip the really slow OpenResFile the next time we start up.
cmp.w #1,d6 ; exit on first time through loop?
bne.s @hadINIT ; no, had an INIT
tst.w d1 ; was the problem not finding a resource?
bz.s @noINITs ; yes, no INITs
cmp.w #resNotFound,d1 ; was the problem not finding a resource?
bne.s @hadINIT ; no, perhaps too little memory
@noINITs
lea BootGlobals.paramBlock(a5),a0 ; point at param block
bset #bFNoINIT,ioFlUsrWds+fdFlags+1(a0) ; remember that there are no INIT resources
move.l d7,ioDirID(a0) ; reset the dirID, since HGetFileInfo trashes it
_HSetFileInfo ; write out the bit
; ignore errors, were just optimizing
@hadINIT
bra NextFileInFolder
; See if AppleTalk is active. If not, dont load the current extension.
@checkAppleTalkState
move.l a0,-(sp) ; <12> Save parameter block
move.l ExpandMem,a0 ; <12>
tst.w ExpandMemRec.emAppleTalkInactiveOnBoot(a0) ; <12> Check saved AppleTalk state
move.l (sp)+,a0 ; <12> Restore parameter block
bz.s @goodFile ; <12> AppleTalk is on. Its ok to load this extension.
bra.s NextFileInFolder ; <12> AppleTalk is off. Dont load this extension.
DoneWithFolder
move.l (sp)+,a4 ; restore a4 for folder. Used for creator type. <9>
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
SetUpForFolder
; Set up a parameter block with the appropriate values, and find a folder to work in.
;
; a5 -> globals, including parameter block and file name storage
; d7.L -> folder type to look for
;
; d0.W <- error code
; d7.L <- dirID of found folder
sub #4,sp ; var foundDirID result
move.l sp,a0
sub #2,sp ; _FindFolder result (OSErr)
move #kOnSystemDisk,-(sp) ; which disk
move.l d7,-(sp) ; which folder type
move.b #kDontCreateFolder,-(sp)
pea BootGlobals.paramBlock+ioVRefNum(a5) ; var foundVRefNum result
move.l a0,-(sp) ; var foundDirID result
_FindFolder
move.w (sp)+,d0
move.l (sp)+,d7
tst.w d0
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
if theFuture then
LoadLinkedPatchFile
; Open a file, and install linked patches from it, using the linked patch loader in the
; system file.
;
; A3 -> Pointer to systems 'ptbl' resource that loads every linked patch.
; D5 -> Pointer to systems patch loader.
;
bsr.s OpenTheFile ; <30> Open the resource file, making it the current resource file
bnz.s @skip ; <30> skip file if the file couldnt be opened.
move.l d5,a0 ; <30> Get the linked patch loader into an address register
jsr (a0) ; <30>Call the linked patch loader.
bsr CloseTheFile ; <30> Close the file now that were done.
@skip
rts ; <30>
endif
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadINITFile
; Open a file, look for a 'sysz', and cycle through the INITs.
; If the system heap must be resized, then must close and reopen the resource file.
;
; a5 -> globals, including parameter block and file name storage
; d7.L -> folder type to look in, then folder dirID
; d6.W <- number of resources loaded
; d1.W <- error result from loading last resource in the file
; d0.W <- error result
; ResErr <- error result
;
; d4.W = refnum of opened file
; d5.L = requested contiguous free space in system zone
;
; To do:
; Change the reality check to a preflight which either chooses to not run the init or to
; skip the allocation and (hopefully) let the init know that the space wasn't allocated.
; Make space before getting 'sysz' to speed up booting, since it reduces re-opening of the file.
move.l #minSysHeapFreeForINIT,d5 ; minimum space needed to run an INIT
bsr MakeSysFree ; resize
bsr.s OpenTheFile ; go open the resource file
bnz.s @skip ; skip file if bad open
; Now look for an 'sysz' resource to make a system heap request.
subq #4,sp ; room for result
move.l #'sysz',-(sp) ; 'sysz' resource
clr.w -(sp) ; id 0 always
_Get1Resource
move.l (sp)+,d0
bz.s @noRequest ; no sysz, go on
move.l d0,a0 ; sysz handle
move.l (a0),a0 ; sysz pointer
move.l (a0),d5 ; requested size
bsr.s MakeSysFree ; get it in the sys zone
@noRequest
cmp.l #'ånd5',A4 ; is this QuickTime™? <9>
bne.s @skipQuickTimeFix ; if not, we dont have to load components <9>
; <40> QuickTime components should not be registered on 68000 machines, since they all
; assume the 020.
cmp.b #cpu68000,CPUFlag ; <40> Are we on a 68000?
beq.s @skipQuickTimeFix ; <40> If so, dont register QuickTimes components
;pascal long RegisterComponentResourceFile(short resRefNum, short global) <9>
clr.l -(sp) ; return value <9>
move.w d4,-(sp) ; fref <9>
move.w #1,-(sp) ; register them globally <9>
moveq #20,d0 ; RegisterComponentResourceFile selector <9>
_ComponentDispatch ; <9>
addq #4,sp ; ignore result <9>
@skipQuickTimeFix
bsr LoadINITResources ; now load all the INIT resources
bsr.s CloseTheFile
_CleanUpApplicationComponents ; clean up any components left in the app heap <9>
@skip
move.w ResErr,d0
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
OpenTheFile
; Open the current resource file with preloading off.
;
; a5 -> globals, including file name at BootGlobals.fileName(a5)
; d7.L -> parent directory id
; d4.W <- file refnum
; d0.W <- error result
; ResErr <- error result
;
; Trashes d0/a0
move.l a1,-(sp)
subq #2,sp ; room for result
move.w #0,-(sp) ; at boot time def. vol. = boot vol.
move.l d7,-(sp)
pea BootGlobals.fileName(a5)
move.b #fsCurPerm,-(sp)
clr.b ResLoad ; no preloads please
_HOpenResFile
st ResLoad ; restore resLoad to proper state
move (sp)+,d4 ; save the refnum
bmi.s @nothingOpened
lea BootGlobals.fileName(a5),a0 ; pointer to files name <30>
move.l a0,CurNamePtr ; Put ptr to the filename into CurApName+4 <35>
@nothingOpened
move.l (sp)+,a1
move.w ResErr,d0
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
CloseTheFile
; Close the current resource file.
;
; d4.W -> file refnum
; d4.W <- -1, indicating no file is open
; Trashes d0/a0
cmp.w #-1,d4
beq.s @done
move.l #-1,CurNamePtr ; no currently-executing file <35>
move d4,-(sp) ; refNum of the open file
_CloseResFile
moveq #-1,d4 ; no file is open
@done
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
MakeSysFree
; Guarantee a contiguous block of free space in the sys. heap.
; If the heap must be grown, must carefully close and reopen the
; current resource file since its map, etc. is in the app heap.
; To avoid purging everything, we use a loop based on _CompactMem
; and _SetAppBase. In the worst case, the loop should be
; executed twice.
;
; d5.L -> requested space
; d4.W -> file refnum, or negative if no resource file is open now
; a5 -> if d4 is positive, name at BootGlobals.fileName(a5)
; d7.L -> if d4 is positive, parent directory id
;
; Trashes d0-d2/a0
;
; To Do:
; Do the CompactMem anyway, even if there is only one zone.
; Add a result code indicating success or failure.
;
; Assertions:
; d1 doesnt get trashed by CloseTheFile, PinSysHeapTop, _SetApplBase, _CompactMem
bsr ApplZoneExists
beq.s @exit ; yes, sys. heap is growable; do nothing
move.w d4,d1 ; save file refNum for later
move.l d5,d0 ; amount needed
_CompactMem sys ; look for it in sys zone
sub.l d5,d0 ; gotten - needed
bge.s @done ; gotten ≥ needed --> done
; d0 is negative <36>
move.l d0,d2 ; size for later
subq.l #1,d2 ; round up and (its negative, so subtract) <36>
and.w #~1,d2 ; make sure it is even
tst.w d4 ; is a resource file open?
bmi.s @noNeedToClose ; no, no need to close the file
bsr.s CloseTheFile ; close resource file
@noNeedToClose
move.l SysZone,a0
move.l bkLim(a0),a0 ; end of sys. zone
sub.l d2,a0 ; end of zone + (needed-gotten)
adda.w #sysHeapFreeSpaceSlop,a0 ; with slop
bsr PinSysHeapTop
_SetApplBase ; free up more space
move.l d5,d0 ; amount needed <36>
_CompactMem sys ; look for it in sys zone again <36>
@done
tst.w d1 ; was there a resource file open?
bmi.s @noNeedToOpen ; no, no need to re-open the file
tst.w d4 ; is the resource file still open?
bpl.s @noNeedToOpen ; yes, no need to re-open the file
bsr OpenTheFile ; assume success here
@noNeedToOpen
bsr RealityCheck ; make sure we have enough memory to continue
@exit
rts
;--------------------------------------------------------------------------------------
;
; Call GetEnvirons to get the system script and GetScript to get that scripts language code
; then pass the information onto the Text Services manager
;
TellTSMScriptAndLanguage
movem.l d3,-(sp) ;save d3
subq #4,sp ;make room for long result from GetScript
move.w #smSysScript,-(sp) ;push the system script verb onto the stack
_GetEnvirons ;get the system script
move.l (sp)+,d3 ;save return value in d3
subq #4,sp ;space for GetScript return value
move.w d3,-(sp) ;put the script (in low word) onto the stack
swap d3 ;now move the script code high
move.w #smScriptLang,-(sp) ;now tell us the language
_GetScript
addq #2,sp ;again we want the low word
move.w (sp)+,d3 ;save the language
subq #4,sp ;make a record on the stack
move.l sp,a0 ;get a pointer to it
move.l d3,(a0) ;copy the S&L infor from d0 into the record we made on the stack
clr.w -(sp) ;clear space for the result
move.l a0,-(sp) ;move the pointer to the stack
_SetTextServiceLanguage ;set the script and language
addq #6,sp ;pop and ignore the result and get rid of the record
movem.l (sp)+,d3 ;restore d3
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadINITResources
; The resource loading loop.
;
; d4.W -> refNum of file were loading from, or -1 meaning the system file
;
; d6.W <- number of resources loaded
; d1.W <- error code
;
; d6.W = index of resource
; d5.L = size needed (used to pass to MakeSysFree)
;
; To Do: store the INIT index and/or handle along with the filename to make
; for easier debugging when files have more than one INIT.
moveq #1,d6 ; start with resource 1
@loop
; First, do a Get1IndResource or a GetResource, from the file or System file.
move.w #mapFalse,ROMMapInsert ; make ResLoad temporarily false, get ROM as well
bsr.s GetINITResource
bnz.s @continue ; got one
; If we didnt get a handle and we are working on a file, we are done.
; If we are working on the System file, we just move on to the next resource by number.
tst.w d4 ; in System?
bpl.s @done ; no, we are done
bra.s @next ; yes, keep going
@continue
; Now make sure there is enough system heap free for us.
subq #4,sp
MOVE.L d1,-(SP) ; resource handle
_SizeRsrc
MOVE.L (SP)+,d5 ; get the size of the INIT
ADD.L #minSysHeapFreeForINIT,d5 ; add the required free space
bsr.s MakeSysFree ; get contiguous bytes in sys. heap
; Make a fresh heap, and get the resource, for real this time.
move.w #mapTrue,ROMMapInsert ; get ROM as well as System file
bsr.s GetINITResource ; now get it for real
bz.s @next ; skip this one if we cant load it
; Detach the resource, if it is one of the ones from the System file.
tst.w d4 ; in System?
bpl.s @noDetach ; no, then dont detach
move.l d1, -(sp) ; yes, push handle to detach <23>
_DetachResource ; and cut it off! <23>
@noDetach
; Lock the sucker down, and call him, preserving registers.
bsr SetBufPtrLimit ; jam MemTop so they wont lower BufPtr too far
bsr.s ExecuteHandle ; execute the stuff in that resource
move.l BootGlobals.logicalMemTop(a5),MemTop ; set MemTop back <30>
@next
addq.w #1,d6 ; up the resource index
tst.w d4 ; in System?
bpl.s @loop ; no, keep going until we cant get any more INITs
cmp.w #36,d6 ; done yet?
blt.s @loop ; no, keep loading
@done
move.w ResErr,d1
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
ExecuteHandle
; Lock and execute the contents of a handle.
;
; d1.L -> handle
;
; Trashes d0-d2/a0-a1
move.l d1,a0 ; resource handle
_HLock ; lock before executing
move.l (a0),d0
_StripAddress
move.l d0,a1 ; get stripped, dereferenced address
move.l (a5),-(sp) ; preserve QD globals pointer
movem.l d3-d7/a2-a6,-(sp) ; save all regs over call
jsr (a1) ; pass handle in a0 for disposing, sizing, etc.
movem.l (sp)+,d3-d7/a2-a6 ; restore regs
move.l (sp)+,(a5)
bsr RealityCheck ; make sure we have enough memory to continue
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
GetINITResource
; d6.W -> ID of INIT resource in System file, or index of INIT resource in another file
; d4.W -> -1 to mean System file, or other to mean current resource file
; d1.L <- handle
; ccr <- Z if resource not found
subq #4,sp ; room for returned handle
move.l #'INIT',-(sp)
move.w d6,-(sp)
tst.w d4 ; from System?
bmi.s @getFromSys
_Get1IxResource ; get indexed from file
bra.s @got
@getFromSys
_GetResource ; get by number from System/ROM
@got
move.l (sp)+,d1
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
HandleMacIIWith030 ; rewrite to simpler, more informed case <48>
; Check for a Mac II ROM with a 68030.
; This specific case handles getting in early enough to tell VM that weve got an 030 (VM-capable).
; Normally, accelerator manufacturers are responsible for setting up CPUFlag, MMUType, and their cache
; settings. Out of the kindness of our hearts, we chose to give this extra support in this one case
; where VM is a new feature, and they cant get in early enough to let VM know they are capable.
;
; MacIIci ROMs and later do all the right setup for CPUFlag, MMUType, and caches.
; MacII ROMs do not.
; Pre-MacII ROMs can't take advantage of VM, so don't help or hurt them.
; Lessons learned:
; You cant turn on CACR_DE_030 even for an instant with some accelerators; they may depend on
; MMU tables being set up and die if they arent.
;
; You cant set MMUType for them. That confuses SwapMMUMode (as evidenced by MacsBug not loading
; because it couldnt find a monitor). Theyll have to provide their own rad SwapMMUMode if they
; want to jam MMUType.
;
; We thought about turning off interrupts during the period were setting CACR_WA_030, but figured
; out that it can never hurt. Check the manual if you dont believe this.
; On Exit: IF actual processor is 68030 & ROM is kROMVersionII
; CPUFlag <- 030
; MMUType unchanged
; CACR unchanged
;
; Destroys: d0-d1/a0. CACR may be touched (WA set briefly) but exits unchanged.
move.l ROMBase,a0 ; point to ROM to get ROM version
cmp.w #kROMVersionII,8(a0) ; do we have a MacII ROM?
bne.s @bail ; no? dont do anything.
cmp.b #cpu68020,CPUFlag ; does the ROM think that this is a 68020?
bne.s @bail ; no? dont do anything.
; we have now decided to second-guess the ROM
MACHINE MC68020
movec cacr,d1 ; temp storage
move.l d1,d0
bset #CACR_WA_030,d0 ; WA, (enable data cache)
movec d0,cacr ; enable data cache (temporarily)
movec cacr,d0 ; IF CACR WA bit != 0 THEN were on an 030 because an 020 doesnt have WA
btst #CACR_WA_030,d0 ; see if the bit exists in CACR by seeing whether it stays set
bz.s @bail ; no? dont do anything.
; dont restore CACR because we just set a bit which doesnt exist
movec d1,cacr ; restore CACR (VERY IMPORTANT: some accelerators cant handle the cache)
move.b #cpu68030,CPUFlag ; its an 030, let everyone know.
; You might be tempted to add setting MMUType. Dont.
@bail
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadVM
; Load the Virtual Memory system, which is contained in the 'ptch' (42) resource (which is locked).
; Also note that VM code contains the true test for whether a machine is “VM capable”.
btst.b #hwCbAUX,HWCfgFlags ; are we under A/UX?
bnz.s @noVM
moveq #cpu68020,d0
cmp.b cpuFlag,d0
blt.s @yesVM
bgt.s @noVM
cmp.b MMUtype,d0
bgt.s @noVM
@yesVM
lea VMName,a0 ; put name of VM into CurApPtr <37>
move.l a0,CurNamePtr ; Put ptr to the VM string <37>
moveq #42,d0
bsr LoadLowerCaseptch ; let VM decide for itself
move.l #-1,CurNamePtr ; no currently-executing file <37>
@noVM
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadDebugger
; Load the MacsBug debugger, and optionally the other debug thing (Disassembler).
; If there is no MacsBug, no attempt is made to load Disassmbler.
; Before loading MacsBug (below BufPtr), 1024 bytes of globals are reserved.
; MacsBug and the Disassembler are responsible for lowering BufPtr themselves after being loaded.
; If they dont, they will be overwritten by the stack and globals of the first application.
SUB.L #debuggerGlobalSize,BufPtr ; leave space for MacsBug globals
btst.b #hwCbAUX,HWCfgFlags ; <24> Are we running under A/UX?
beq.s @loadDebugger ; <24> No
sub.l #auxExtraDebuggerSize,BufPtr ; <24> MacsBug needs more room under A/UX
@loadDebugger
lea BootGlobals.bootBlocks+bbDbg1Name(a5),a1
bsr.s LoadBelowBufPtrSkip512 ; try loading it
BEQ.S @install ; if present, install it
ADD.L #debuggerGlobalSize,BufPtr ; otherwise, dealloc MacsBug globals
BRA.S @done
@install
lea DebuggerName,a0 ; put name of MacsBug into CurApPtr <37>
move.l a0,CurNamePtr ; Put ptr to the MacsBug string <37>
JSR (a2) ; tell it to install itself
; NOTE: the following code must not change in length - MacsBug depends upon it (blegh!)
; If MacsBug punts, it adds the magic offset 6 (bytes, that is) to the return address
; to skip over this code. Ideally, the interface should allow the debugger to return
; an error code (in, say, D0?) to allow happy bypassing of this message.
MOVEQ #dsMacsBugInstalled,D0 ; alert saying we got MacsBug
bsr BootAlert ; display it if we should <42>
; If we loaded the debugger successfully, get the Disassembler, too.
lea BootGlobals.bootBlocks+bbDbg2Name(a5),a1
bsr.s LoadBelowBufPtrSkip512 ; search for Disassembler
BNE.S @done ; branch if theres no disassembler
lea DisassemblerName,a0 ; put name of Disassembler into CurApPtr <37>
move.l a0,CurNamePtr ; Put ptr to the Disassembler string <37>
JSR (a2) ; tell it to install itself
; see above NOTE for MacsBug: the disassembler works the same way
MOVEQ #dsDisassemblerInstalled,D0 ; alert saying we got the disassembler
bsr BootAlert ; display it if we should <42>
@done
move.l #-1,CurNamePtr ; nothing currently executing <37>
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
BootAlert
; BootAlert posts the boot alert specified; it may be disabled if there is a startup screen.
;
; d0.W -> the boot alert number (must be negative).
; d7.B -> 0 to disable boot alerts.
tst.b d7 ; did we get a startup screen?
bz.s @skip ; if we did, skip
_SysError ; post the alert
@skip
rts
string pascal ; names used to identify culprits
VMName dc.b 'Virtual Memory'
align
DebuggerName dc.b 'Debugger'
align
DisassemblerName dc.b 'Disassembler'
align
LinkedPatchName dc.b 'System'
align
string asis
; ——————————————————————————————————————————————————————————————————————————————————————————————————
; Load the data fork of a file into high memory (just below BufPtr).
LoadBelowBufPtrSkip512
moveq #64,d1
lsl.w #3,d1 ; 64*8 = 512
bra.s LoadBelowBufPtrCommon
LoadBelowBufPtr
moveq #0,d1
LoadBelowBufPtrCommon
; a1 -> name for file to load
; d1.L -> number of bytes to skip at the start of the file
; a5 -> boot globals (used to find place for parameter block)
; a2 <- location loaded
; d2.L <- size of file loaded 0 means failure
; d3.B <- 0 = successfully loaded (CCRs set)
;
; Trashes d0-d3/a0-a2.
lea BootGlobals.paramBlock(a5),a0
MOVEQ #-1,d3 ; error code
LEA ioFileName(A0),A2 ; point to params we use
MOVE.L A1,(A2)+ ; ioFileName(A0)
CLR.L (A2)+ ; ioDrvNum(A0), ioRefNum(A0) use default drive?
CLR.B (A2)+ ; ioFileType(A0) type 0
MOVE.B #fsRdPerm,(A2)+ ; read-only permissions
lea BootGlobals.fileBuffer(a5),a1
move.l a1,(A2) ; ioOwnBuf(A0) use space after boot blocks
_Open
BNE.S @fail
_GetEOF
BNE.S @close
MOVE.L (A2)+,d2 ; ioLEOF(A0) get physical length in bytes
SUB.L d1,d2 ; skip first block
MOVE.L BufPtr,A2 ; get top of code stack
SUB.L d2,A2 ; A2 = where to read into
LEA ioBuffer(a0),a1
MOVE.L A2,(a1)+ ; ioBuffer(A0)
MOVE.L d2,(a1)+ ; ioByteCount(A0)
ADDQ #ioPosMode-ioNumDone,a1
MOVE.W #fsFromStart,(a1)+ ; ioPosMode(A0) absolute positioning
MOVE.L d1,(a1) ; ioPosOffset(A0) start at 512
_Read
BNE.S @close
MOVEQ #0,d3 ; no errors
@close
_Close
@fail
tst.b d3 ; test result for CCR
RTS
; ——————————————————————————————————————————————————————————————————————————————————————————————————
LoadPTCH
move.l #'PTCH',d1 ; fall through
bra.s DetachAndExecute
LoadLowerCaseptch
move.l #'ptch',d1 ; load one of these
DetachAndExecute
; Loads, detaches, and executes the resource with given type and ID.
;
; D0.W -> patch resource id
; D1.L -> patch resource type
; D2.L -> bufPtrs lower limit (added for the file cache) <33>
;
; Trashes: d0-d1/a0
;
; Patches are called with their handle in D1.L.
SUBQ #4,SP ; make room on the stack
MOVE.L d1,-(SP)
MOVE.W d0,-(SP)
_GetResource ; get the resource handle
MOVE.L (SP)+,D1 ; save the resource handle
BEQ.S @skip
MOVE.L D1,-(SP) ; detach it
_DetachResource
MOVE.L D1,A0 ; get the handle
MOVE.L (A0),D0 ; handle -> pointer
_StripAddress
MOVEA.L D0,A0
movem.l A3-A6, -(SP) ; save important registers
jsr (A0) ; call it (note that the handle must be in D1)
movem.l (SP)+, A3-A6 ; restore cause ptch/PTCH trashes these
@skip
RTS
; ——————————————————————————————————————————————————————————————————————————————————————————————————
ApplZoneExists
move.l ApplZone,d0
cmp.l SysZone,d0
rts
CreateApplicationHeap
bsr.s ApplZoneExists
bne.s @clobberIt ; if an ApplZone exists, kill it, otherwise …
move.l BufPtr,ApplZone ; fool InitApplZone into thinking we had no zone before
@clobberIt
_InitApplZone ; make the heap and clean up if there was an old one
move.l sp,a0 ; current stack
sub.l DefltStack,a0 ; leave room for INITs to work
_SetApplLimit
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
MakeSystemHeapGrowable
; Set things up so the system heap and the application heap are the same, so the system heap will
; grow (this is only needed for the Plus and the SE, other ROMs do something like this already).
bsr.s ApplZoneExists
beq.s @noApplZone ; if no ApplZone exists, no need to kill it
_InitApplZone
@noApplZone
move.l SysZone,a0 ; calculate a new minimum size for the heap
add.l #initialSysHeapSize,a0 ; make it big enough so it wont need to grow much
bsr.s PinSysHeapTop ; dont go farther than we really can
_SetApplBase ; SetApplBase will never shrink the heap
move.l SysZone,a0 ; the one true heap
move.l a0,ApplZone ; coincident heaps
move.l a0,TheZone ; make it the current heap too
move.l bkLim(a0),HeapEnd ; end of dynamic system/application heap
move.l sp,a0 ; find the stack
sub.l DefltStack,a0 ; keep room for the stack
sub.l #minBootAppHeapSize,a0 ; and the application heap
_SetApplLimit ; this is the highest we should grow
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
PinSysHeapTop ; <34>
; Things above sysZone include the stack (which starts in the middle) and applZone (if any).
; This is only called when SysZone is being made ApplZone so it can grow, so there is never
; an ApplZone to worry about. However, we do have to leave room so we can create one later.
;
; Other things above that include: this code (on the stack), BufPtr, MemTop.
;
; a0 -> where they think they want the top of heap
; a0 <- where they get to put the top of the system heap
;
; Trashes a1
;
; To Do:
; Consider the case where the recommended top of the sysheap/bottom of the app heap is lower
; than the current top of the system heap. Bad, but what should happen? We can't cut into
; the stack or app heap sizes, can we? Maybe we just stop trying to load inits because we
; ran out of room. How would we get into this state, anyway? Would it (could it) ever happen?
move.l sp,a1
sub.l DefltStack,a1 ; leave room for the stack
sub.l #minBootAppHeapSize,a1 ; leave room for an app heap later <34>
sub.l BootGlobals.reservedForAfterBoot(a5),a1 ; leave room for post-boot <34>
cmp.l a0,a1
bhi.s @ok
move.l a1,a0
@ok
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
TemporaryNewPtrStartup ; <30>
; This is a routine to lower BufPtr. Its usable only during startup.
; Another routine is used after startup is through.
; -> d0.L logicalSize
; <- a0 address of allocated block (Nil on failure)
; <- d0 result code
; memFullErr
; Error is also reported in MemErr
;
; _NewPtrStartup ,CLEAR will clear the allocated block.
movem.l d2-d3,-(sp) ; save params and work registers
move.w d1,d3 ; save trap word in d3
addq.l #3,d0 ; round up to nearest multiple of 4 <30>
andi.b #$FC,d0
move.l d0,d2 ; save amount requested in d2
move.l BufPtr,d1
sub.l d0,d1 ; proposed new BufPtr value
bcs.s @allocationFailed ; they asked for something bigger than BufPtr
bsr.s IsThisBufPtrOK ; see if this d1 will work as a new value of BufPtr
bne.s @allocationFailed
andi.b #$FC,d1 ; drop it to the next longword
move.l d1,a0 ; address of allocated block
move.l a0,BufPtr ; make the allocation
btst #clearBit,d3 ; is this a NewPtrStartup ,CLEAR?
beq.s @dontClear
move.l d2,d1 ; size to clear out
move.l a0,a1 ; pointer to block
bsr.s ClearBlock ; clear out the block at BufPtr as requested
@dontClear
movem.l (sp)+,d2-d3
clr.l d0 ; set the result code
move.w d0,MemErr ; set MemErr
rts
@allocationFailed
movem.l (sp)+,d2-d3
; fall through into JustReturnAnError
JustReturnAnError ; <30>
; This is used for NewPtrStartup after startup time.
move.l #0,a0 ; return nil
move.w #memFullErr,d0 ; allocation failed
move.w d0,MemErr ; set MemErr
rts
JustReturnAnErrorEnd
; ——————————————————————————————————————————————————————————————————————————————————————————————————
ClearBlock
; -> d1.L logicalSize (must be multiple of 4)
; -> a1 start of block to zero
;
; Trashes a1
lsr #2,d1 ; d1 := d1 / 4
subq #1,d1 ; make it zero-based
@loop clr.l (a1)+
dbf d1,@loop
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
SetBufPtrLimit
; This sets MemTop to a value which will put a (faked-up) limit on how far BufPtr may be lowered.
; Its based on the rule that BufPtr may not be lowered past MemTop / 2 + 1024. We believe that
; many INITs use this rule, so we also expect that they will stop where we want them to when they
; use our computed value of MemTop.
;
; Things which limit BufPtrs descent:
; must have at least 350K + stack space to launch Finder
; must have at least ???K + stack space to launch some essential control panel
; NuBus™ cards or ROM in the logical memory space (when VM is in 24 bit mode
;
; a5 -> globals
; MemTop <- 2 * (bufPtrLimit - 1K)
;
; Trashes a0/d0
;
; fake MemTop -> FakeMemTop will always be ≥ MemTop
; MemTop -> +_____________
; |
; |
; BufPtr -> |
; |
; |………………………………… <- if 24bit VM, then barrier = BootGlobals.bufPtrLimit(a5)
; |## NuBus™ ## <- may be here if in 24bit VM mode
; |
; |### ROM #### <- ditto
; |
; |
; |------------- <- SysZone + minProcessMgrSpace (could be below barrier)
; |
; |
; |————————————— <- barrier = BootGlobals.lowestBufPtr(a5)
; boot code -> |±±±±±±±±±±±±± BufPtr cant go lower than this without killing the machine.
; boot globals-> |≠≠≠≠≠≠≠≠≠≠≠≠≠
; top of stack-> |\\\\\\\\\\\\\
; |\\\ stack \\\
; SP -> |\\\\\\\\\\\\\
; |
; ApplZone … … … … … … … …
; SZ.bkLim -> |
; |
; |
; SysZone -> |_____________
; | lomem globs
; +—————————————
bsr AdjustBarrier ; <38>
move.l BootGlobals.bufPtrLimit(a5),a0 ; <38>
sub.w #1024,a0 ; minBufPtr - 1024
add.l a0,a0 ; 2*(minBufPtr - 1024) <30>
move.l a0,MemTop ; MemTop := 2*(minBufPtr - 1024)
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
RealityCheck
; This boolean routine returns EQ if there is sufficient space in the system heap to accomodate
; the amount requested in D0.
;
; Trashes d0-d1/a0
; Actually just fall through to the next routine, but we might eventually want to check other
; things, like the size of or the amount of free space in the system heap.
; ——————————————————————————————————————————————————————————————————————————————————————————————————
IsBufPtrOK
; Has BufPtr moved too far down?
;
; Trashes d0-d1/a0
move.l BufPtr,d1
bsr.s IsThisBufPtrOK
beq.s @yes
move.w #dsMemFullErr,d0
_SysError
@yes
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
IsThisBufPtrOK ; <30>
; Would it be OK to lower BufPtr to the place suggested by d1?
;
; 1. Moved past the boot-time barrier. This is a test for whether boot globals would be smashed.
; 2. Consumed so much room we wont have room to launch Finder.
;
; a5 -> globals
; d1.L -> suggested BufPtr
; CCRs <- Z if successful
;
; Trashes d1/a0
; Have we gone past the boot globals or the limit imposed by VM?
move.l BootGlobals.bufPtrLimit(a5),a0 ; a0 := top of the barrier <33><30>
cmp.l a0,d1 ; barrier < suggested BufPtr?
blo.s @no ; nope, we need our boot globals
; Is there enough space to build the Process Mgr. heap?
move.l SysZone,a0
move.l bkLim(a0),a0
sub.l a0,d1 ; any space above the system heap?
blo.s @no ; nope, we need our system heap <30>
cmp.l #minProcessMgrSpace,d1 ; space >= min Process Mgr. size?
blo.s @no ; nope, not enough to create the heap & stack
moveq #0,d1 ; set CCR for success (Z)
@no ; all failure cases set CCR for failure (not Z)
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
AdjustBarrier ; <38>
; Adjust BootGlobals.bufPtrLimit(a5) to have:
; MAX( sysHeap.bkLim + minProcessMgrSpace, static limits (i.e. boot globals & vm limits) )
; Trashes: a0/d0
move.l SysZone,a0
move.l a0,d0 ; copy baseAddr of SysZone
move.l bkLim(a0),a0
add.l #initialSysHeapSize,d0
cmp.l d0,a0 ; if heap is small because were on a small RAM machine
bhs.s @enoughReservedForSysHeap ; pretend heap is at initialSysHeapSize because it will
; be that big soon anyway.
move.l d0,a0 ; Set to be the minimum wed ever consider.
@enoughReservedForSysHeap
add.l #minProcessMgrSpace,a0 ; where the process mgr heap would end if we
; created it right now
cmp.l BootGlobals.bufPtrLimit(a5),a0 ; processMgrHeap.bkLim > current barrier?
bls.s @dont ; if not, dont adjust
move.l a0,BootGlobals.bufPtrLimit(a5) ; set new barrier
@dont
rts
; ——————————————————————————————————————————————————————————————————————————————————————————————————
TemporaryStripAddress
; This is a copy of StripAddress used on the Plus and SE during initialization.
; Another copy in the patches is used after initialization is through.
AND.L Lo3Bytes,D0
RTS
; ——————————————————————————————————————————————————————————————————————————————————————————————————
EraseMyIcon
; Get rid of the happy Macintosh icon.
; The ROMs leave this icon on the screen and now that we have taken part of the
; boot process away from the ROM we need to erase that icon. For the old ROMs we
; call the EraseMyIcon routine in ROM wherever that happens to be in each specific
; ROM.
btst.b #hwCbAUX,HWCfgFlags ; are we under A/UX?
bnz.s @noErase
move.l ROMBase,a0 ; point to ROM
move.w 8(a0),d0 ; get ROM version
lea EraseMyIconTable,a1 ; point to table of EraseMyIcon routine offsets
@next
move.w (a1)+,d1 ; next ROM version
bz.s @noErase
move.w (a1)+,d2 ; ROM offset
cmp.w d0,d1 ; the right ROM?
bne.s @next ; no, go on to the next one
jmp 0(a0,d2.w) ; call the routine
@noErase
rts
EraseMyIconTable
; This is a table of the routines used to erase the startup icon on various machines.
; A better approach would be a trap or vector, for new ROMs.
dc.w kROMVersionII,$18A4 ; II
dc.w kROMVersionPortable,$2B0C ; Portable
dc.w kROMVersionIIci,$17DA ; IIci
dc.w 0
; ——————————————————————————————————————————————————————————————————————————————————————————————————
CenterOnMainScreen
; Center a rectangle on the main screen. The rectangle is passed on the stack.
; The rectangle is modified in place on the stack (a rectangle, not a pointer to it).
;
; stack -> rectangle is passed in on top of the stack
;
; Trashes d0-d2/a0-a1
lea 4(sp),a0 ; get pointer to the rectangle in question
move.l a0,-(sp) ; push rectangle pointer
moveq #2,d0 ; push horizontal offset
bsr.s @pushOffset
moveq #0,d0 ; push vertical offset
bsr.s @pushOffset
_OffsetRect ; offset the rectangle
rts ; and return
@pushOffset
; Push offset for the rectangle = screenTop - rectTop + screenHeight - rectHeight.
; Because screenBits.bounds.topLeft is (0, 0) this simplifies to offsetting by
; (screenBits.bounds.bottom - rect.bottom - rect.top) / 2.
;
; This is all described in terms of the Y dimension, but works for the X dimension, too.
;
; a5 -> globals
; a0 -> pointer to rectangle
; d0.W -> dimension (0 for Y, 2 for X)
; stack <- routine pushes the offset onto the stack
;
; Trashes d1/a1
move.l (sp)+,a1 ; get return address
move.w BootGlobals.quickDrawGlobals.screenBits+bounds+botRight(a5,d0.W),d1
sub.w botRight(a0,d0.W),d1
sub.w topLeft(a0,d0.W),d1
asr.w #1,d1 ; divide by 2
move.w d1,-(sp) ; move this offset onto the stack
jmp (a1) ; return
; ——————————————————————————————————————————————————————————————————————————————————————————————————
CachesOffMFMPatch
MOVE.L (SP)+,DskRtnAdr ;Save return address
MOVEA.L IWM,A4
LEA wData(A4),A3 ;Point to write data and
LEA rHandshake(A4),A4 ; handshake registers for speed
MOVE.B #$F5,wPhase-wData(A3) ;select another drive address (in this case x101)
; to avoid the drive's index crosstalk problem
TST.B rError-wData(A3) ;Clear the error register
MOVE.B #$18,wZeroes-wData(A3) ;Clear the write and action bits
MOVE.B #$10,wOnes-wData(A3) ;Set the write bit
MOVE.B #$01,wOnes-wData(A3) ;Toggle the clFIFO bit to clear out
MOVE.B #$01,wZeroes-wData(A3) ; any data in the FIFO
TST.B rError-wData(A3) ;Clear the error register again for grins
; Delay a bit then write the sync bytes before the data mark to position
; the sector data in the correct location relative to the address header.
; We'll poll the SCC while we wait to keep the CompuServe types happy that
; we're not losing precious bytes of gossip while we're saving stuff to disk...
MOVE.W #kNoCacheWriteAdj,D0 ; write splice timing constant
JMP $4086EFF4 ; Jump back into the ROM WrData code on Quadra 700 (Spike).
EndCachesOffMFMPatch EQU *
EndOfBootCode
; ——————————————————————————————————————————————————————————————————————————————————————————————————
end