mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 16:31:01 +00:00
0ba83392d4
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
546 lines
16 KiB
C
546 lines
16 KiB
C
/*
|
|
File: Startup.c
|
|
|
|
Contains: Main startup for the Process Manager.
|
|
|
|
Written by: Erich Ringewald
|
|
|
|
Copyright: © 1986-1993 by Apple Computer, Inc., all rights reserved.
|
|
|
|
Change History (most recent first):
|
|
|
|
<SM28> 7/21/93 joe Back out <SM27>.
|
|
<27> 10/28/92 DTY Use new Get/Set macros to access ExpandMem.
|
|
<26> 9/25/92 DRF Get rid of MyGestalt, since inline glue exists
|
|
<25> 8/26/92 DTY Change ModSquadÕs funky conditional to use #ifdefs like everyone
|
|
else.
|
|
<24> 8/26/92 DTY Roll in latest changes for A/UX.
|
|
<23> 8/17/92 hjcr Adding support for OCE's "defer drag" feature. Conditionally
|
|
compiled under MODSQUAD
|
|
<22> 5/11/92 JSM #1029437 <DC>: Set emProcessMgrExists to true after calling
|
|
MyNewGestalt().
|
|
<21> 3/30/92 DTY #1025416,<DDG>: Look for Skia in InitConfig and set skiaExists
|
|
accordingly.
|
|
<20> 3/23/92 JSM OSEvents.h is obsolete, use Events.h.
|
|
<19> 1/11/92 YK Initialize new globals for the TSM.
|
|
<18> 11/22/91 DTY Initialize allocateGMBlkInSysHeap to be false. GMBlk normally
|
|
tries to allocate itÕs block in the Process Manager zone first,
|
|
except when an 'obit' event is being sent.
|
|
<17> 11/1/91 DTY Set TOPMAPHANDLE to point to the first system override map
|
|
instead of SYSMAPHANDLE in main().
|
|
<16> 10/15/91 YK Added initializing code for the Text Service Manager.
|
|
<15> 9/16/91 DFH Set initialProcessSR in InitializeScheduler. Needed for
|
|
NuKernel.
|
|
<14> 5/23/91 dba do a style of coercion that MPW 3.2 C likes
|
|
<13> 1/28/91 DFH JSM,#81425: Removed inhibit_DAs mechanism.
|
|
<12> 1/15/91 DFH (VL) Conditionalize out FloatAUXUp.
|
|
<11> 1/14/91 DFH (dba) Make system mode per process.
|
|
<10> 1/14/91 DFH (JDR) Conditionalize out AUX support.
|
|
<8> 1/8/91 DFH (rdd) Got rid of pErrantProcess since it is no longer needed.
|
|
<7> 12/15/90 DFH Main now initializes srcMyScrapInfo.pScrapOwner.
|
|
<6> 12/14/90 DFH InitializeScheduler now initializes kernelMode.
|
|
<5> 12/13/90 JWM For 7.0B3, sending the AppleEvent message to the network
|
|
extension (Network Setup) in the shell program (Finder 7.0)
|
|
about the PPCToolbox not initializing was removed.
|
|
<4> 12/5/90 DFH Integrated AUX support.
|
|
<3> 11/26/90 DFH Change trespass() to dbmsg().
|
|
<0> 9/2/86 ELR New Today.
|
|
|
|
*/
|
|
|
|
#pragma segment INIT
|
|
|
|
#include <types.h>
|
|
#include <memory.h>
|
|
#include <menus.h>
|
|
#include <files.h>
|
|
#include <quickdraw.h>
|
|
#include <events.h>
|
|
#include <resources.h>
|
|
#include <scrap.h>
|
|
#include <osutils.h>
|
|
#include <retrace.h>
|
|
#include <fonts.h>
|
|
#include <dialogs.h>
|
|
#include <textedit.h>
|
|
#include <segload.h>
|
|
#include <errors.h>
|
|
#include <GestaltEqu.h>
|
|
#include <EPPC.h>
|
|
#include <AppleEventsInternal.h>
|
|
#include <MFPrivate.h>
|
|
#include <ResourceMgrPriv.h>
|
|
|
|
#include "Lomem.h"
|
|
#include "SysMisc.h"
|
|
#include "Glue.h"
|
|
#include "Data.h"
|
|
#include "OSDispatchPrivate.h"
|
|
#include "Patches.h"
|
|
#include "Aux.h"
|
|
#include "Puppet.h"
|
|
#include "HList.h"
|
|
#include "Zone.h"
|
|
#include "EppcPrivate.h"
|
|
#include "AppleEventExtensions.h"
|
|
|
|
/* Some function prototypes that should be in (yet another) header file */
|
|
void MyNewGestalt(void);
|
|
void InitExceptions(void);
|
|
void GetSwitchTab(void);
|
|
void InitSystemMenus(void);
|
|
void VNInit(void);
|
|
void FMKill(Boolean);
|
|
|
|
/* Function prototypes internal to this file */
|
|
void InitializeEnvironment(void);
|
|
void InitializeScheduler(void);
|
|
void InitConfig(void);
|
|
void FloatMainUp(void);
|
|
void FloatKernelUp(void);
|
|
void FloatEppcUp(void);
|
|
void FloatAUXUp(void);
|
|
|
|
main(void)
|
|
{
|
|
LaunchResults finderLaunchResults;
|
|
Handle ourScrapHdl;
|
|
HighLevelEventRecord theEvent;
|
|
FSSpec finderSpec;
|
|
|
|
_DataInit(); /* Initialize our global data */
|
|
InitializeEnvironment(); /* Adjust machine environment to our liking */
|
|
InstallPatches(); /* Install our patches */
|
|
InitializeScheduler(); /* Initialize our global structures */
|
|
|
|
/* Locate Process Mgr's scrap handle BEFORE launches */
|
|
ourScrapHdl = SCRAPHANDLE;
|
|
|
|
/* In case BG app dies before we launch FINDERNAME */
|
|
pShellProcess = ((Ptr) -1);
|
|
|
|
/* Launch startup background applications */
|
|
if ((EXTENSIONSENABLEBYTE & (1 << ExtensionsEnabledBit)) != 0)
|
|
LaunchFacelessTasks();
|
|
|
|
THEZONE = ProcessMgrZone;
|
|
if ((finderLaunchResults.LaunchError = FSMakeFSSpec(BOOTVOL, 0, FINDERNAME, &finderSpec)) == noErr)
|
|
StandardLaunch(&finderSpec, launchUseMinimum, 0, nil, &finderLaunchResults, nil);
|
|
|
|
/* Quick Restore: Have to set zone to sys to do _UnloadSeg correctly */
|
|
THEZONE = SYSZONE; CURMAP = SYSMAP; TOPMAPHANDLE = GetOverrideMap(SYSMAPHANDLE);
|
|
|
|
/* Bomb box if the Finder launch failed */
|
|
if (finderLaunchResults.LaunchError != noErr)
|
|
SysError(dsFinderErr);
|
|
|
|
/* Remember who we launched from this special place of honor */
|
|
pShellProcess = finderLaunchResults.pNewProcess;
|
|
pShellProcess->p_dadProcess = nil;
|
|
ShellWasFinderType = IS_FINDER(pShellProcess);
|
|
|
|
/* Dump scrap since we don't use it */
|
|
if (ourScrapHdl != nil)
|
|
DisposHandle(ourScrapHdl);
|
|
|
|
/* Next Process Mgr call should use Process Mgr stack as kernel stack */
|
|
kernelstack = initCurStackBase;
|
|
|
|
/* Prepare to execute Finder */
|
|
coercionState = CS_INIT;
|
|
srcMyScrapInfo.pScrapOwner = pFrontProcess = pShellProcess;
|
|
pFrontProcess->p_state = PRRUN;
|
|
|
|
/* Unload initialization code before leaving, and also
|
|
* remove the handle from the system res map.
|
|
* NOTE: This leaves us running in a dead code segment. But the current
|
|
* Resource Manager and Memory Manager let us get away with this
|
|
* for now. All we need to do is make the switch_task call, since its
|
|
* code is in another segment, and will never return.
|
|
*/
|
|
{
|
|
CodeEntry *pCodeEntry; /* Needed explicitly because of C compiler bug */
|
|
|
|
pCodeEntry = InitializeEnvironment;
|
|
UnloadSeg(pCodeEntry);
|
|
ReleaseResource(GET_SCOD_HDL_FROM_FNC_PTR(pCodeEntry));
|
|
}
|
|
|
|
/* Send Finder AppleEvents a) to say that machine was just booted, and b) to give a
|
|
* message to the network extension if PPC wouldn't initialize.
|
|
*/
|
|
SetAppleEvent(aeStartup, &theEvent);
|
|
(void) BeginSystemMode();
|
|
(void) PostHighLevelEvent((EventRecord *) &theEvent, (u_long) &pShellProcess->p_serialNumber, 0, nil, 0, receiverIDisPSN);
|
|
|
|
/* For 7.0B3 the message to the network extension in the shell program about the
|
|
* PPCToolbox not initializing was removed. No one to support Responder, so it
|
|
* was rewritten.
|
|
*/
|
|
|
|
(void) EndSystemMode();
|
|
|
|
/* Switch to the Finder we launched, never to return (hopefully) */
|
|
switch_task(pFrontProcess);
|
|
dbmsg("Illegal return to the Process Manager.");
|
|
}
|
|
|
|
|
|
/* Dummy routines to force load of CODE segments */
|
|
#pragma segment Main
|
|
|
|
void
|
|
FloatMainUp(void)
|
|
{
|
|
}
|
|
|
|
#pragma segment kernel_segment
|
|
|
|
void
|
|
FloatKernelUp(void)
|
|
{
|
|
}
|
|
|
|
#pragma segment eppc_segment
|
|
|
|
void
|
|
FloatEppcUp(void)
|
|
{
|
|
}
|
|
|
|
#ifdef HAS_AUX_PROCESSMGR
|
|
#pragma segment AUX_SEGMENT
|
|
|
|
/* null procedure so that segment can get loaded appropriately */
|
|
void FloatAUXUp(void)
|
|
{
|
|
}
|
|
#endif HAS_AUX_PROCESSMGR
|
|
|
|
#pragma segment INIT
|
|
|
|
/* This is the size we give the system heap at startup. It's exact value is somewhat
|
|
* unimportant. It mainly determines how many times we'll have to call the System
|
|
* zone or Process Mgr zone GrowZone procedures before things settle out. Make sure
|
|
* it's small enough that the initial Finder launch goes smoothly.
|
|
*/
|
|
#define INIT_SYS_HEAP_SIZE (96*1024)
|
|
|
|
/* InitializeEnvironment. Set up the initial world (i.e. heap, qd globals, etc.). */
|
|
void
|
|
InitializeEnvironment(void)
|
|
{
|
|
CodeEntry *pCodeEntry;
|
|
register OSDispatchEntry *pDispatchEntry;
|
|
|
|
/* Set up our own lomem A5 ptr */
|
|
PROCESSMGRGLOBALS = CURRENTA5;
|
|
|
|
/* Save initial location zero before we call any traps that might change it! */
|
|
initLocationZero = LOCATIONZERO;
|
|
|
|
/* Get configuration information */
|
|
InitConfig();
|
|
|
|
/* Get table of switchable low memory locations (in System Heap) */
|
|
GetSwitchTab();
|
|
|
|
/* Expand the zone up to the APPLLIMIT */
|
|
MaxApplZone();
|
|
|
|
/* initialize the scrap, if necessary */
|
|
THEZONE = SYSZONE;
|
|
if (SCRAPSTATE == (-1))
|
|
(void) ZeroScrap();
|
|
THEZONE = APPLZONE;
|
|
|
|
/* Unload data init seg and release its CODE resource (to get it out of map). */
|
|
pCodeEntry = _DataInit;
|
|
UnloadSeg(pCodeEntry);
|
|
ReleaseResource(GET_SCOD_HDL_FROM_FNC_PTR(pCodeEntry));
|
|
|
|
/* Set up dynamic heaps */
|
|
InitHeaps();
|
|
|
|
THEZONE = SYSZONE;
|
|
|
|
/* Load in the code segments now that zone expansion code is in place */
|
|
FloatMainUp();
|
|
FloatKernelUp();
|
|
FloatEppcUp();
|
|
#ifdef HAS_AUX_PROCESSMGR
|
|
if (AUXIsPresent)
|
|
FloatAUXUp();
|
|
#endif HAS_AUX_PROCESSMGR
|
|
|
|
/* Alter dispatch table to go directly to routine, bypassing the jump table */
|
|
pDispatchEntry = &OSDispatchTable[0];
|
|
while (pDispatchEntry->dispatchAddr != nil)
|
|
{
|
|
pDispatchEntry->dispatchAddr = ROUTINE_ADDR(pDispatchEntry->dispatchAddr);
|
|
pDispatchEntry += 1;
|
|
};
|
|
|
|
/* Make sure PROCESSMGRGLOBALS world is reasonable */
|
|
InitGraf(&qd.thePort);
|
|
#ifdef MM_DEBUG
|
|
{
|
|
pascal void DebugNotifyPurge(void);
|
|
extern Ptr oldPurgeProc;
|
|
|
|
oldPurgeProc = (Ptr)SYSZONE->purgeProc;
|
|
SYSZONE->purgeProc = (ProcPtr)DebugNotifyPurge;
|
|
}
|
|
#endif MM_DEBUG
|
|
|
|
/* Initialize window manager in system heap ('cause it's shared in our patch)
|
|
* NOTE: Calls InitFonts for InitWindow's sake on older machines.
|
|
*/
|
|
InitFonts();
|
|
InitWindows();
|
|
MFLayer = GetCurLayer();
|
|
IMLayer = nil;
|
|
THEZONE = APPLZONE;
|
|
|
|
#ifdef HAS_AUX_PROCESSMGR
|
|
/* Adjust ourselves to running under AUX */
|
|
if (AUXIsPresent)
|
|
AUX_Setup();
|
|
#endif HAS_AUX_PROCESSMGR
|
|
|
|
/* We want to run from the boot volume. */
|
|
SetVol(nil, BOOTVOL);
|
|
|
|
/* Set up volume notification mechanism */
|
|
VNInit();
|
|
}
|
|
|
|
/* GetKernelMode. Inline to fetch the processor's SR and save it sans all bits
|
|
* except the supervisor/user mode one.
|
|
*/
|
|
#pragma parameter GetKernelMode(__A0)
|
|
void
|
|
GetKernelMode(short *storage)
|
|
= {0x40C0, 0x0240, 0x2000, 0x3080};
|
|
/* MOVE SR,D0
|
|
* ANDI.W #$2000,D0
|
|
* MOVE.W D0,(A0)
|
|
*/
|
|
|
|
/* InitializeScheduler. Now that our machine environment looks good, prepare our data
|
|
* structures so we can run applications.
|
|
*/
|
|
void
|
|
InitializeScheduler(void)
|
|
{
|
|
PEntryPtr pProc;
|
|
Handle hdl;
|
|
u_size currSysHeapSize;
|
|
extern StringPtr SSSPromptpStr, MacOSPortNamepStr;
|
|
|
|
/* Initialize these before calling InitExceptions() because the exception
|
|
* handlers will want to look at them.
|
|
*/
|
|
pProc = pCurrentProcess = pNullProcess;
|
|
|
|
/* Install our exception handlers */
|
|
InitExceptions();
|
|
|
|
/* initialize the process list globals */
|
|
ProcessNumberSource = LowestNonSystemPSN;
|
|
ProcessIDSource = MAX_PROCESSID;
|
|
pProcessList = nil;
|
|
pFrontProcess = pNullProcess;
|
|
|
|
/* we are taking over the nullprocess */
|
|
MemClear(pProc, sizeof(PEntry));
|
|
pProc->p_state = PRNULL;
|
|
pProc->p_signature = NULLPROC_SIGNATURE;
|
|
pProc->p_version = SYS_VERSION;
|
|
SetPSN(kSystemProcess, &pProc->p_serialNumber);
|
|
pProc->p_zone = THEZONE;
|
|
pProc->p_size = (unsigned long) BUFPTR - (unsigned long) THEZONE;
|
|
|
|
/* Save useful startup values */
|
|
initialProcessSR = GetCPUStatusRegister() & (kCPUSupervisorMode | kCPUMasterStack);
|
|
initMemTop = MEMTOP;
|
|
initFSQueueHook = FSQUEUEHOOK;
|
|
|
|
/* Get the stack for kernel use set up. */
|
|
initCurStackBase = CURSTACKBASE;
|
|
kernelstack = nil;
|
|
kernelstackbase = (unsigned long) APPLZONE->bkLim;
|
|
GetKernelMode(&kernelMode);
|
|
|
|
/* Because app zone can't grow anymore */
|
|
kernelbusy = 0;
|
|
|
|
/* initialize the state lists */
|
|
pSleepingStateList = nil;
|
|
pDyingStateList = nil;
|
|
|
|
/* Now init some of the more mundane things. */
|
|
pDebugProcess = nil;
|
|
debugKeyTryCount = -1; /* Based on -1 as start */
|
|
pSystemQuitAllMsg = nil;
|
|
pLastBGProcess = nil;
|
|
nbacks = 0;
|
|
cutCopyCount = 0;
|
|
dont_switch = 0;
|
|
napOver = false;
|
|
(void) GetDeskPort((GrafPtr *) &desklayer);
|
|
desklayerowner = nil;
|
|
SystemTempMemHList = CreateHList(0);
|
|
|
|
/* Allocate handle for supporting the Text Service Manager */
|
|
fakeKeyHandle = (FakeKeyHandle)NewHandle( 0);
|
|
fakeKeyCount = 0;
|
|
dontGetFakeKey = 0;
|
|
tsmLayerOwner = nil;
|
|
routeEvent = false;
|
|
|
|
/* Get all the resources we need. Do the Process Mgr ones first. Wait to do system
|
|
* ones until we have THEZONE == SYSZONE. See note below.
|
|
*/
|
|
THEZONE = SYSZONE;
|
|
|
|
/* Get menu strings for scrap coercion */
|
|
hdl = Get1Resource('STR#',-16414);
|
|
pStrListCopyNamePrefix = (hdl == nil) ? nil : *((StrListHdl)hdl);
|
|
|
|
/* Get the strings for ePPC */
|
|
SSSPromptpStr = nil;
|
|
MacOSPortNamepStr = nil;
|
|
if ((hdl = Get1Resource('STR#',-16457)) != nil)
|
|
{
|
|
SSSPromptpStr = *hdl+(Ptr)2;
|
|
MacOSPortNamepStr = (Ptr)SSSPromptpStr + (Ptr)(*(char *)SSSPromptpStr);
|
|
MacOSPortNamepStr += (Ptr)1;
|
|
}
|
|
|
|
/* <18> This semaphore is only true when an 'obit' event is being sent from
|
|
SendDeathNotice. Set it to false to start off. */
|
|
allocateGMBlkInSysHeap = false;
|
|
|
|
/* Make sure there is some minimum sys heap size so we won't call
|
|
* the grow zone proc so many times to launch Finder.
|
|
*/
|
|
currSysHeapSize = (Ptr)SYSZONE->bkLim - (Ptr)SYSZONE;
|
|
if (currSysHeapSize < INIT_SYS_HEAP_SIZE)
|
|
(void)ProcessMgrSysGZProc(INIT_SYS_HEAP_SIZE - currSysHeapSize);
|
|
|
|
/* Initialize the puppet strings */
|
|
PuppetStringsInit();
|
|
|
|
/* Get rid of old system resources that were in the system heap */
|
|
THEZONE = APPLZONE;
|
|
RsrcZoneInit();
|
|
|
|
/* Switch to SYSZONE because any of the _GetResource calls below could move
|
|
* memory within the call, which is a problem for the rsrc mgr routine
|
|
* CheckLoad(). It saves and restores THEZONE, but our heap can move so restoring
|
|
* the "original" value is incorrect.
|
|
*/
|
|
THEZONE = SYSZONE;
|
|
{
|
|
/* Get the standard MDEF for the system menus. We must do this because some apps
|
|
* (like Finder!) aren't picky about what they get. We need a good version!
|
|
*/
|
|
long mdef = 'MDEF';
|
|
short mdefIndex = 0;
|
|
long mdefVersionID = 0;
|
|
Handle realMDefHdl;
|
|
|
|
#define SMALLEST_GOOD_MDEF_ID (13)
|
|
|
|
while (mdefVersionID < SMALLEST_GOOD_MDEF_ID)
|
|
{
|
|
if ((realMDefHdl = GetResource(mdef, mdefIndex)) == nil)
|
|
{
|
|
/* Couldn't find any tables */
|
|
assert(RESERR == memFullErr);
|
|
SysError(dsMemFullErr);
|
|
}
|
|
|
|
/* NOTE: Create struct for this */
|
|
mdefVersionID = *((unsigned long *)(*((Handle)realMDefHdl) + 8));
|
|
mdefIndex++;
|
|
}
|
|
|
|
standardMenuDefProcRsrc = (Handle) StripAddress(realMDefHdl);
|
|
}
|
|
|
|
/* Insert the system menus now that we have the MDEF */
|
|
InitSystemMenus();
|
|
|
|
/* Get rid of useless font width tables, etc. Must be done after InitSystemMenus,
|
|
* because menu installers need font info set up.
|
|
*/
|
|
FMKill(false);
|
|
|
|
/* Announce our arrival */
|
|
MyNewGestalt();
|
|
|
|
/* Let other parts of system software know we are here without having to call the gestalt routine we just installed */
|
|
SetExpandMemProcessMgrExists((short)true);
|
|
|
|
/* Initialize the Event Program to Program Communication (can load drivers) */
|
|
ePPCInit();
|
|
|
|
/* End of sys resources */
|
|
THEZONE = ProcessMgrZone;
|
|
}
|
|
|
|
/* InitConfig. Set up hardware/software configuration information, based on the
|
|
* word of our wonderboy, Gestalt. Only gets the info we actually need. Sets
|
|
* defaults if selector not installed. The defaults are somewhat impossible to
|
|
* know for FPU and keyboard types, but their selectors should always be safe.
|
|
*/
|
|
void
|
|
InitConfig(void)
|
|
{
|
|
long gestaltResult;
|
|
|
|
/* set defaults in case selector undefined */
|
|
In32BitMode = false;
|
|
Colorized = false;
|
|
MachineHasFPU = false;
|
|
MachineHasMacPlusKbd = false;
|
|
#ifdef HAS_AUX_PROCESSMGR
|
|
AUXIsPresent = false;
|
|
#endif HAS_AUX_PROCESSMGR
|
|
|
|
/* Check processor addressing mode */
|
|
if (Gestalt(gestaltAddressingModeAttr,&gestaltResult) == noErr)
|
|
In32BitMode = ((gestaltResult & (1 << gestalt32BitAddressing)) != 0);
|
|
|
|
/* Check QuickDraw version */
|
|
if (Gestalt(gestaltQuickdrawVersion,&gestaltResult) == noErr)
|
|
Colorized = ((gestaltResult & 0xFFFF) >= gestalt8BitQD);
|
|
|
|
/* Does this machine have an FPU? */
|
|
if (Gestalt(gestaltFPUType,&gestaltResult) == noErr)
|
|
MachineHasFPU = (gestaltResult != gestaltNoFPU);
|
|
|
|
/* Does this machine have an older style keyboard (without an escape key)? */
|
|
if (Gestalt(gestaltKeyboardType,&gestaltResult) == noErr)
|
|
MachineHasMacPlusKbd = (gestaltResult <= gestaltMacPlusKbd);
|
|
|
|
if (Gestalt(gestaltGraphicsVersion,&gestaltResult) == noErr)
|
|
skiaExists = true;
|
|
else
|
|
skiaExists = false;
|
|
|
|
#ifdef MODSQUAD
|
|
/* Check whether drag manager is installed. */
|
|
if (Gestalt(gestaltDragMgrVersion, &gestaltResult) == noErr)
|
|
gDragMgrIsAvailable = true;
|
|
#endif
|
|
|
|
#ifdef HAS_AUX_PROCESSMGR
|
|
/* Check whether we're running under AUX. */
|
|
if (Gestalt(gestaltAUXVersion, &gestaltResult) == noErr && AUX_EnableCoffLaunch())
|
|
AUXIsPresent = true;
|
|
#endif HAS_AUX_PROCESSMGR
|
|
}
|