commit 1f23cecf7f2b4fd615ad2249fb7b83098fae9c96 Author: Jeffrey Paul Date: Fri Mar 29 09:35:52 2019 -0700 initial diff --git a/Bonus Junk/MegaBoot.c b/Bonus Junk/MegaBoot.c new file mode 100755 index 0000000..b226786 --- /dev/null +++ b/Bonus Junk/MegaBoot.c @@ -0,0 +1,492 @@ +#include +#include +#include + +#pragma parameter __D0 VMMap( __A0, __A1 ) +OSErr VMMap( UInt32 log, UInt32 phys ) TWOWORDINLINE( 0x7007, 0xfe0a ); +#pragma parameter __D0 VMUnmap( __A0, __A1 ) +OSErr VMUnmap( UInt32 log, UInt32 key ) TWOWORDINLINE( 0x7008, 0xfe0a ); + +UInt8 gWindowStor[ 0x1fff ]; +UInt32 gWindowPage; + +struct { + UInt8 flags[4]; + DrvQEl dqe; +} gMyDQE; +UInt32 gActualSize = 0x08000000 >> 9; + +typedef struct PhysRun { + UInt32 startPage; + UInt32 numBytes; +} PhysRun; + +PhysRun gRuns[] = { { 0x0c000000 >> 12, 0x08000000 } }; +int gNumRuns = 1; + +extern OSErr __Startup__(); +extern void DriverHeader(); +extern void main(void); +extern void CallBootResource( Handle ); +extern OSErr DriverOpen(); +extern OSErr DriverClose(); +extern OSErr DriverPrime( IOParamPtr:__a0, DCtlPtr:__a1 ); +extern OSErr DriverStatus( CntrlParamPtr:__a0, DCtlPtr:__a1 ); +extern OSErr DriverControl( CntrlParamPtr:__a0, DCtlPtr:__a1 ); +extern void NumToHex( UInt32, UInt8 * ); +void PrintTrap( UInt16 trap ); +void UltimatePatch(); + + +asm OSErr __Startup__() { + subq #4, sp // gimme that return ptr back! + + pea (a3) + _DetachResource // no return value + + move.l a4, -(sp) + jsr SetCurrentA4 // boot block calling conventions are pretty freestyle + + jsr main + + move.l (sp)+, a4 + + move.l (sp), a0 + move.w (a0)+, -(sp) + jsr PrintTrap + addq #2, sp + + move.w (a0)+, -(sp) + jsr PrintTrap + addq #2, sp + + move.w (a0)+, -(sp) + jsr PrintTrap + addq #2, sp + + move.w (a0)+, -(sp) + jsr PrintTrap + addq #2, sp + + move.w (a0)+, -(sp) + jsr PrintTrap + addq #2, sp + + move.w (a0)+, -(sp) + jsr PrintTrap + addq #2, sp +// move.w #dsSystemFileErr, d0; + move.w #resNotFound, d0; + rts +} + +ExitCodeResource(); +} + + +asm void DriverHeader() { + dc.w dNeedLockMask | dStatEnableMask | dCtlEnableMask | dReadEnableMask | dWritEnableMask + dc.w 0 // delay + dc.w 0 // evt mask + dc.w 0 // menu + + dc.w 0x1a + dc.w 0x1e + dc.w 0x28 + dc.w 0x32 + dc.w 0x3c + + dc.b "\p.RAMB0" + +@open: + jmp DriverOpen +@prime: + movem.l a0/a1, -(sp) + jsr DriverPrime + bra.s @finish +@control: + movem.l a0/a1, -(sp) + jsr DriverControl + bra.s @finish +@status: + movem.l a0/a1, -(sp) + jsr DriverStatus + bra.s @finish +@close: + jmp DriverClose + +@finish: + movem.l (sp)+, a0/a1 + move.w 6 (a0), d1 // PB.ioTrap + btst # noQueueBit, d1 + bne.s @rtn + + move.l 0x8fc, -(sp) // jIODone + +@rtn: + move.w d0, 0x10 (a0) // PB.ioResult + rts +} + + +extern OSErr DriverOpen() { + return noErr; +} + + +void PrintTrap( UInt16 trap ) { + UInt8 trapstr[8]; + EnterCodeResource(); + + NumToHex( trap, trapstr ); + ISDebugText( trapstr+4, 4 ); + + ExitCodeResource(); +} + + +asm void UltimatePatch() { + movem.l a0/a1/d0/d1, -(sp) + + move.l 0x12 (sp), a0 + move.w (a0), -(sp) + jsr PrintTrap + addq #2, sp + + movem.l (sp)+, a0/a1/d0/d1 + jmp 0x80000000 +} + + +asm long SetCurrentA4() { + lea __Startup__,a0 + adda.l #305419896,a0 + move.l a0,d0 + exg d0,a4 + rts +} + +extern OSErr DriverPrime( IOParamPtr pb:__a0, DCtlPtr dce:__a1 ) { + OSErr err = noErr; + UInt32 ioPage, ioPen; + int bcnt; + + EnterCodeResource(); + ISDebugStr( ( pb->ioTrap & 0xff ) == aRdCmd? "\pI" : "\pO" ); + + pb->ioActCount = 0; + VMUnmap( gWindowPage, 1 ); + + while ( pb->ioActCount < pb->ioReqCount ) { + UInt32 maxTrans, actTrans; + Ptr disk, buff; + + for ( bcnt = 0, ioPen = dce->dCtlPosition + pb->ioActCount; bcnt < gNumRuns && gRuns[bcnt].numBytes <= ioPen; bcnt++ ) { + ioPen -= gRuns[bcnt].numBytes; + } + if ( bcnt == gNumRuns ) { + err = ioErr; + break; + } + + VMMap( gWindowPage, gRuns[bcnt].startPage + ( ioPen >> 12 ) ); + + maxTrans = 0x1000 - ( ioPen & 0xfff ); + actTrans = pb->ioReqCount - pb->ioActCount; + actTrans = (maxTransioBuffer + pb->ioActCount; + + if ( pb->ioTrap & 0xff == aRdCmd ) { + BlockMoveData( disk, buff, actTrans ); + } else { + BlockMoveData( buff, disk, actTrans ); + } + + VMUnmap( gWindowPage, 1 ); + + pb->ioActCount += actTrans; + } + ISDebugStr( "\pDone" ); + + ExitCodeResource(); + return err; +} + + +extern OSErr DriverControl( CntrlParamPtr pb:__a0, DCtlPtr dce:__a1 ) { + EnterCodeResource(); + ISDebugStr( "\pC" ); + ExitCodeResource(); + return controlErr; +} + +extern OSErr DriverStatus( CntrlParamPtr pb:__a0, DCtlPtr dce:__a1 ) { + EnterCodeResource(); + ISDebugStr( "\pS" ); + ExitCodeResource(); + return statusErr; +} + +extern OSErr DriverClose + + +void main( void ) { + OSErr err = noErr; + VCBPtr bootV; + SInt16 bootD; + CntrlParam pb; + SInt16 myRN; + UInt32 dlong; + EnterCodeResource(); + + InitInterruptSafeDebug(); + * ( (UInt32 *) ( (UInt32) UltimatePatch + 0x16 ) ) = * (UInt32 *) 0x28; + //* ( (UInt32 *) 0x28 ) = (UInt32) &UltimatePatch; + ISDebugStr( "\pRAMB03" ); + Delay( 200, &dlong ); + + gWindowPage = ( (UInt32) &gWindowStor + 0xfff ) >> 12; + HoldMemory( (Ptr) ( gWindowPage << 12 ), 0x1000 ); + VMUnmap( gWindowPage, 1 ); + ISDebugStr( "\pphysical fenestration" ); + + { // close the system file & knock the resource manager silly + //CloseResFile( LMGetSysMap() ); + /*LMSetTopMapHndl( NULL ); + LMSetCurMap( 1 );*/ + LMSetSysMapHndl( NULL ); + LMSetSysMap( 1 ); + } + + { // unmount the boot vol + ISDebugStr( "\pSys closed" ); + pb.ioCompletion = NULL; + + bootV = (VCBPtr) GetVCBQHdr()->qHead; + bootD = bootV->vcbDrvNum; + + pb.ioVRefNum = bootV->vcbVRefNum; + pb.ioNamePtr = NULL; + + //err = PBUnmountVol( (ParmBlkPtr) &pb ); + } + + if ( err == noErr ) { // install our drvr + ISDebugStr( "\pVol unmounted" ); + err = TradInstallDriverFromPtr( (DRVRHeaderPtr) &DriverHeader, 48, 127, &myRN ); + } + + if ( err == noErr ) { + err = OpenDriver( "\p.RAMB0", &myRN ); + } + + if ( err == noErr ) { // find the boot drive & link in after it + DrvQElPtr dqe; + SInt16 highDrive = 0; + + for ( dqe = (DrvQElPtr) GetDrvQHdr()->qHead; dqe->dQDrive != bootD; dqe = (DrvQElPtr) dqe->qLink ) { + if ( dqe->dQDrive > highDrive ) highDrive = dqe->dQDrive; + } + + gMyDQE.dqe.qLink = dqe->qLink; + dqe->qLink = (QElemPtr) &gMyDQE.dqe; + + for ( dqe = (DrvQElPtr) gMyDQE.dqe.qLink; dqe; dqe = (DrvQElPtr) dqe->qLink ) { + if ( dqe->dQDrive > highDrive ) highDrive = dqe->dQDrive; + } + + gMyDQE.flags[0] = 0; // unlocked + gMyDQE.flags[1] = 8; // nonejectable + gMyDQE.flags[2] = 0; // reserved + gMyDQE.flags[3] = 0; // n/a + gMyDQE.dqe.dQDrive = highDrive + 1; + gMyDQE.dqe.dQRefNum = myRN; + gMyDQE.dqe.dQFSID = 0; + gMyDQE.dqe.dQDrvSz = (UInt16) gActualSize; + gMyDQE.dqe.dQDrvSz2 = (UInt32) gActualSize >> 16; + + PrintTrap( myRN ); + } + + if ( err == noErr ) { + HVolumeParam vpb; + DrvQElPtr dqe; + + vpb.ioVRefNum = gMyDQE.dqe.dQDrive; + vpb.ioVolIndex = 0; + vpb.ioNamePtr = NULL; + vpb.ioCompletion = 0; + + err = PBMountVol( (ParmBlkPtr) &vpb ); + + if ( err == noErr ) { + ISDebugStr( "\pmounted RAM disk" ); + err = PBHGetVInfoSync( (HParmBlkPtr) &vpb ); + } + + for ( dqe = (DrvQElPtr) GetDrvQHdr()->qHead; dqe && ( err || vpb.ioVFndrInfo[0] == 0 ); dqe = (DrvQElPtr) dqe->qLink ) { + err = PBUnmountVol( (ParmBlkPtr) &vpb ); + + vpb.ioVRefNum = dqe->dQDrive; + err = PBMountVol( (ParmBlkPtr) &vpb ); + + if ( vpb.ioVRefNum == bootD ) err = dsBadStartupDisk; // no recursion! + + vpb.ioVolIndex = 0; + if ( err == noErr ) { + ISDebugStr( "\pmounted something else" ); + err = PBHGetVInfoSync( (HParmBlkPtr) &vpb ); + } + } + + if ( dqe == NULL ) err = dsBadStartupDisk; + +/* pb.ioVRefNum = 15; //gMyDQE.dqe.dQDrive; + + err = PBMountVol( (ParmBlkPtr) &pb ); + } + + if ( err == noErr ) { + HVolumeParam vpb; + vpb.ioVRefNum = pb.ioVRefNum; + vpb.ioVolIndex = 0; + vpb.ioNamePtr = 0; + vpb.ioCompletion = 0; + + err = PBHGetVInfoSync( (HParmBlkPtr) &vpb );*/ + + if ( err == noErr ) { + LMSetBootDrive( vpb.ioVDrvInfo ); + + ( (WDPBPtr) &vpb )->ioWDDirID = vpb.ioVFndrInfo[0]; + ( (WDPBPtr) &vpb )->ioWDProcID = 'ERIK'; // Erik... that's me ;v) + + err = PBOpenWDSync( (WDPBPtr) &vpb ); + } + + if ( err == noErr ) { + ISDebugStr( "\pFound a System Folder" ); + err = PBSetVolSync( (ParmBlkPtr) &vpb ); + } + } + + if ( err == noErr ) { + ISDebugStr( "\pSet the sys folder" ); + Delay( 60, &dlong ); + /*if ( InitResources() < 0 ) { + err = dsSystemFileErr; + ISDebugStr( "\pNo InitResources() for U" ); + }*/ + LMSetSysMap( OpenResFile( LMGetSysResName() ) ); + + Delay( 60, &dlong ); + if ( LMGetSysMap() == 0 ) err = fnfErr; + } + + if ( err == noErr ) { + Handle boot2; + OSType type; + SInt16 id, rx = 1; + UInt8 check[8]; + + LMSetSysMapHndl( LMGetTopMapHndl() ); + + do { + boot2 = GetIndResource( 'boot', rx ); + err = ResError(); + GetResInfo( boot2, &id, &type, check ); + PrintTrap( id ); + PrintTrap( rx ); + NumToHex( * (UInt32 *) *boot2, check ); + ISDebugText( check, 8 ); + rx++; + } while( err == noErr && * (UInt32 *) *boot2 != 0x204ba025 ); + + Delay( 300, &dlong ); + + ISDebugStr( "\pCalling boot" ); + if ( err == noErr ) { + * ( (UInt32 *) 0x28 ) = (UInt32) &UltimatePatch; + CallBootResource( boot2 ); + } + } + + { + UInt8 errstr[8]; + NumToHex( err, errstr ); + ISDebugText( errstr, 8 ); + + ISDebugStr("\preturning"); + Delay( 600, &dlong ); + } + + ExitCodeResource(); +} + + +asm void CallBootResource( Handle boot2 ) { + movea.l 4 (sp), a3 + movea.l (a3), a0 + jmp (a0) +} + + +void NumToHex( UInt32 num, UInt8 *hex ) { + int ncnt; + + for ( ncnt = 0; ncnt < 8; ncnt++ ) { + int nibble = ( num >> (28-ncnt*4) ) & 0x0f; + nibble += (nibble>9)?('a'-10):'0'; + + hex[ncnt] = nibble; + } +} + + + /*if ( err == noErr ) { + pb.ioVRefNum = gMyDQE.dqe.dQDrive; + + err = PBMountVol( (ParmBlkPtr) &pb ); + } + + if ( err == noErr ) { + ISDebugStr( "\pMounted" ); + + SetVol( NULL, pb.ioVRefNum );*/ + +/*void main(void) { + Ptr windowStor, window; + UInt32 lcnt; + + SetCurrentA4(); + + InitInterruptSafeDebug(); + + ISDebugStr( "\pHello" ); + + Delay(60, &lcnt); + window = (Ptr) ( ( (UInt32) &gWindowStor + 0xfff ) & ~0xfff ); + HoldMemory( window, 0x1000 ); + + VMUnmap( ( (UInt32) window ) >> 12, 1 ); + VMMap( ( (UInt32) window ) >> 12, 0 ); + + for ( lcnt = 0; lcnt < 4; lcnt++ ) { + UInt8 hstr[9]; + *hstr = 8; + + NumToHex( ( (UInt32 *) window )[lcnt], hstr + 1 ); + + ISDebugStr( hstr ); + } + + VMUnmap( ( (UInt32) window ) >> 12, 1 ); + UnholdMemory( window, 0x1000 ); + //Debugger(); + Delay(600, &lcnt); + +}*/() { + return noErr; +} \ No newline at end of file diff --git a/Open Firmware/install.f b/Open Firmware/install.f new file mode 100755 index 0000000..ba21083 --- /dev/null +++ b/Open Firmware/install.f @@ -0,0 +1 @@ +\ Open Firmware script to install Ephemerboot hex 70.0.74.77.a unselect-dev " true" " use-nvramrc?" $setenv " : ram-boot "" hd:,"(5c):tbxi"" $boot ;" nvramrc $setenv " ram-boot" " boot-command" $setenv " 04000000" " ramboot-disk-size" $setenv ." Set nv vars" cr \ No newline at end of file diff --git a/Open Firmware/ramboot b/Open Firmware/ramboot new file mode 100755 index 0000000..c8cc6d8 --- /dev/null +++ b/Open Firmware/ramboot @@ -0,0 +1 @@ + MacRISC Pre-bootloader clips visible RAM to allocate a RAM disk. hex 70.0.74.77.a unselect-dev " /options" find-package drop constant _options " /memory" find-package drop constant _memory 2.00000 constant reboot-reserved-space : boot-tbxj " &device;:&partition;,"(5c):tbxj" 2dup open-dev if $boot then ." RAMBoot: Deferring to selected physical disk. 2drop mac-boot ; struct 4 field >next-run 4 field >start-addr 4 field >byte-count constant /phys-run variable first-phys-run first-phys-run " reg" _memory get-package-property drop begin ( run addr len ) dup while decode-int >r ( run addr len ) rot ( addr len run ) /phys-run alloc-mem dup >r ( addr len run newrun ) swap ! ( addr len ) r> ( addr len newrun ) r> over >start-addr ! ( addr len newrun ) -rot decode-int >r ( newrun addr len ) rot ( addr len newrun ) r> over >byte-count ! dup >start-addr @ ." Encoded range " . dup >byte-count @ ." , " . cr >next-run -rot repeat 2drop off first-phys-run @ begin dup >next-run @ ?dup while nip repeat >r r@ >byte-count @ reboot-reserved-space - dup r@ >byte-count ! r> >start-addr @ + constant reserved-run-start 0 first-phys-run @ begin tuck >byte-count @ + swap >next-run @ ?dup 0= until constant total-ram " ramboot-disk-size" _options get-package-property if ." RAMBoot: could not get prefs from NVRAM" boot-tbxj then \ decode-int decode-string $number drop constant disk-ram 2drop : encode-int+ encode-int encode+ ; : encode-start >start-addr @ encode-int+ ; : encode-count >byte-count @ encode-int+ ; 0 0 encode-bytes total-ram disk-ram - dup 0< if 3drop ." RAMBoot: specified size larger than installed memory." boot-tbxj then first-phys-run @ begin ( addr len rem run ) tuck >byte-count @ ( addr len run rem count ) over < while ( addr len run rem ) >r >r ( addr len ) r@ encode-start r@ encode-count r> r> ( addr len run rem ) over >byte-count @ - swap ( addr len rem run ) >next-run @ repeat swap >r -rot ( rem addr len ) r@ encode-start 2 pick encode-int+ reserved-run-start encode-int+ reboot-reserved-space encode-int+ " /memory" find-device " reg" 2dup delete-property property unselect-dev ( rem ) ." done with /memory" cr dup r@ >start-addr @ + encode-int rot ( addr len rem ) r@ >byte-count @ swap - ?dup 0<> if encode-int+ else 2drop 0 0 encode-bytes then r> >next-run @ ( addr len run ) begin ?dup while >r r@ encode-start r@ encode-count r> >next-run @ repeat " /chosen" find-device " ramboot-phys-ranges" property unselect-dev " /options" find-device " ramboot-checksum" _options get-package-property 0= if " ramboot-checksum" 2dup delete-property property then unselect-dev boot-tbxj  \ No newline at end of file diff --git a/Open Firmware/ramboot-src b/Open Firmware/ramboot-src new file mode 100755 index 0000000..f253414 --- /dev/null +++ b/Open Firmware/ramboot-src @@ -0,0 +1 @@ +hex 70.0.74.77.a unselect-dev " /options" find-package drop constant _options " /memory" find-package drop constant _memory 2.00000 constant reboot-reserved-space : boot-tbxj " &device;:&partition;,"(5c):tbxj" 2dup open-dev if $boot then ." RAMBoot: Deferring to selected physical disk. 2drop mac-boot ; struct 4 field >next-run 4 field >start-addr 4 field >byte-count constant /phys-run variable first-phys-run first-phys-run " reg" _memory get-package-property drop begin ( run addr len ) dup while decode-int >r ( run addr len ) rot ( addr len run ) /phys-run alloc-mem dup >r ( addr len run newrun ) swap ! ( addr len ) r> ( addr len newrun ) r> over >start-addr ! ( addr len newrun ) -rot decode-int >r ( newrun addr len ) rot ( addr len newrun ) r> over >byte-count ! dup >start-addr @ ." Encoded range " . dup >byte-count @ ." , " . cr >next-run -rot repeat 2drop off first-phys-run @ begin dup >next-run @ ?dup while nip repeat >r r@ >byte-count @ reboot-reserved-space - dup r@ >byte-count ! r> >start-addr @ + constant reserved-run-start 0 first-phys-run @ begin tuck >byte-count @ + swap >next-run @ ?dup 0= until constant total-ram " ramboot-disk-size" _options get-package-property if ." RAMBoot: could not get prefs from NVRAM" boot-tbxj then \ decode-int decode-string $number drop constant disk-ram 2drop : encode-int+ encode-int encode+ ; : encode-start >start-addr @ encode-int+ ; : encode-count >byte-count @ encode-int+ ; 0 0 encode-bytes total-ram disk-ram - dup 0< if 3drop ." RAMBoot: specified size larger than installed memory." boot-tbxj then first-phys-run @ begin ( addr len rem run ) tuck >byte-count @ ( addr len run rem count ) over < while ( addr len run rem ) >r >r ( addr len ) r@ encode-start r@ encode-count r> r> ( addr len run rem ) over >byte-count @ - swap ( addr len rem run ) >next-run @ repeat swap >r -rot ( rem addr len ) r@ encode-start 2 pick encode-int+ reserved-run-start encode-int+ reboot-reserved-space encode-int+ " /memory" find-device " reg" 2dup delete-property property unselect-dev ( rem ) ." done with /memory" cr dup r@ >start-addr @ + encode-int rot ( addr len rem ) r@ >byte-count @ swap - ?dup 0<> if encode-int+ else 2drop 0 0 encode-bytes then r> >next-run @ ( addr len run ) begin ?dup while >r r@ encode-start r@ encode-count r> >next-run @ repeat " /chosen" find-device " ramboot-phys-ranges" property unselect-dev " /options" find-device " ramboot-checksum" _options get-package-property 0= if " ramboot-checksum" 2dup delete-property property then unselect-dev boot-tbxj \ No newline at end of file diff --git a/Patch Partition/BuildpDES/BuildpDES b/Patch Partition/BuildpDES/BuildpDES new file mode 100755 index 0000000..e69de29 diff --git a/Patch Partition/BuildpDES/BuildpDES Data/BuildpDES/TargetDataMacOS.tdt b/Patch Partition/BuildpDES/BuildpDES Data/BuildpDES/TargetDataMacOS.tdt new file mode 100755 index 0000000..ebaefe1 Binary files /dev/null and b/Patch Partition/BuildpDES/BuildpDES Data/BuildpDES/TargetDataMacOS.tdt differ diff --git a/Patch Partition/BuildpDES/BuildpDES Data/CWSettingsMacOS.stg b/Patch Partition/BuildpDES/BuildpDES Data/CWSettingsMacOS.stg new file mode 100755 index 0000000..889197f Binary files /dev/null and b/Patch Partition/BuildpDES/BuildpDES Data/CWSettingsMacOS.stg differ diff --git a/Patch Partition/BuildpDES/BuildpDES.SYM b/Patch Partition/BuildpDES/BuildpDES.SYM new file mode 100755 index 0000000..b8d52b9 Binary files /dev/null and b/Patch Partition/BuildpDES/BuildpDES.SYM differ diff --git a/Patch Partition/BuildpDES/BuildpDES.c b/Patch Partition/BuildpDES/BuildpDES.c new file mode 100755 index 0000000..f970442 --- /dev/null +++ b/Patch Partition/BuildpDES/BuildpDES.c @@ -0,0 +1,49 @@ +//BuildpDES.c +//©5/18/02 David "Potatoswatter" Krauss + +#include + + +extern UInt16 DriverChecksum( Handle dH ) { + UInt32 bcnt; + UInt32 sum; + + sum = 0; + for ( bcnt = 0; bcnt < GetHandleSize( dH ); bcnt++ ) { + sum += (UInt8) *( *dH + bcnt ); + sum <<= 1; + if ( sum & 0x10000 ) sum |= 1; + } + + if ( (UInt16) sum == 0 ) { + sum = -1; + PtrToXHand( &sum, dH, 1 ); + + return DriverChecksum( dH ); + } + + return sum; +} + + +void main( void ) { + Handle patch; + PatchDescriptor **pd; + + patch = Get1Resource( 'ptch', 128 ); + DetachResource( patch ); + pd = (PatchDescriptor **) Get1Resource( 'pDES', 128 ); + DetachResource( (Handle) pd ); + + (**pd).patchDescriptorLen = ( GetHandleSize((Handle)pd) + 1 ) & ~1; + (**pd).patchCRC = DriverChecksum( patch ); + (**pd).patchSize = GetHandleSize( patch ); + + OpenResFile( "\pEphemerboot Installer" ); + + RemoveResource( Get1Resource( 'pDES', 128 ) ); + AddResource( (Handle) pd, 'pDES', 128, "\p" ); + + RemoveResource( Get1Resource( 'ptch', 128 ) ); + AddResource( patch, 'ptch', 128, "\p" ); +} \ No newline at end of file diff --git a/Patch Partition/BuildpDES/BuildpDES.mcp b/Patch Partition/BuildpDES/BuildpDES.mcp new file mode 100755 index 0000000..e769c8a Binary files /dev/null and b/Patch Partition/BuildpDES/BuildpDES.mcp differ diff --git a/Patch Partition/BuildpDES/Ephemerboot Installer b/Patch Partition/BuildpDES/Ephemerboot Installer new file mode 100755 index 0000000..3c4fd0e Binary files /dev/null and b/Patch Partition/BuildpDES/Ephemerboot Installer differ diff --git a/Patch Partition/BuildpDES/TemplatepDES.rsrc b/Patch Partition/BuildpDES/TemplatepDES.rsrc new file mode 100755 index 0000000..e69de29 diff --git a/Patch Partition/Ephemerboot Data/CWSettingsMacOS.stg b/Patch Partition/Ephemerboot Data/CWSettingsMacOS.stg new file mode 100755 index 0000000..09bbfee Binary files /dev/null and b/Patch Partition/Ephemerboot Data/CWSettingsMacOS.stg differ diff --git a/Patch Partition/Ephemerboot Data/MegaBoot/TargetDataMacOS.tdt b/Patch Partition/Ephemerboot Data/MegaBoot/TargetDataMacOS.tdt new file mode 100755 index 0000000..7a1b0a9 Binary files /dev/null and b/Patch Partition/Ephemerboot Data/MegaBoot/TargetDataMacOS.tdt differ diff --git a/Patch Partition/Ephemerboot.c b/Patch Partition/Ephemerboot.c new file mode 100755 index 0000000..9b94b4b --- /dev/null +++ b/Patch Partition/Ephemerboot.c @@ -0,0 +1,698 @@ +//RAMBoot.c - boot 9 from RAM. +//©5/18/02 - 5/27/02 David "Potatoswatter" Krauss - v1.0.0c1 + +#include +#include +#include +#include + +#pragma parameter __D0 VMMap( __A0, __A1 ) +OSErr VMMap( UInt32 log, UInt32 phys ) TWOWORDINLINE( 0x7007, 0xfe0a ); +#pragma parameter __D0 VMUnmap( __A0, __A1 ) +OSErr VMUnmap( UInt32 log, UInt32 valid ) TWOWORDINLINE( 0x7008, 0xfe0a ); + +Ptr gWindowStor; +UInt32 gWindowPage; +Ptr gDiskWindowPtr; +Ptr gSumWindowPtr, gSum2WindowPtr; + +struct { + UInt8 flags[4]; + DrvQEl dqe; +} gMyDQE; +UInt32 gActualSize = 0; + +typedef struct PhysRun { + UInt32 startPage; + UInt32 numBytes; +} PhysRun; + +PhysRun *gRuns; +UInt32 gNumRuns; + +enum { + kPageSize = 0x1000, + kPageBits = 0xfffff000, + + kSumBoxVolume = kPageSize, // one page per sum box + kSumBoxVolumeLog2 = 12, + kSumBoxSide = 8, // box is square array of lattices + kSumBoxSideLog2 = 3, + kSumBoxDimensions = 4, // plus one more for depth + kSumBoxDepth = 1, // bytes, tho the true depth is in bits + + kSumBytesPerPage = kSumBoxSide * kSumBoxDimensions * kSumBoxDepth, + kSumRatio = kSumBoxVolume / kSumBytesPerPage, + + kMaxDimensions = kSumBoxDimensions +}; +Ptr gCurSumPtr; +UInt32 gCurSumPhys; +UInt32 gSumBase; + +Ptr gCurSum2Ptr; +UInt32 gCurSum2Phys; +UInt32 gSum2Base; + +Ptr gCurSum3Ptr; +Ptr gSum3Ptr; +UInt32 gSum3Size; +Ptr gSum3Str; +UInt32 gSum3StrSize; + + +const char gTreeChosen[] = "Devices:device-tree:chosen"; +const char gPhysRunsProp[] = "ramboot-phys-ranges"; + +const char gTreeOptions[] = "Devices:device-tree:options"; +const char gSumPropertyName[] = "ramboot-checksum"; +RegEntryID gOptionsEntry; + + +extern pascal OSErr main(void); + +extern void DriverHeader(); +extern OSErr DriverOpen(); +extern OSErr DriverClose(); +extern OSErr DriverPrime( IOParamPtr:__a0, DCtlPtr:__a1 ); +extern OSErr DriverStatus( CntrlParamPtr:__a0, DCtlPtr:__a1 ); +extern OSErr DriverControl( CntrlParamPtr:__a0, DCtlPtr:__a1 ); + +extern pascal OSErr GestaltProc( UInt32, SInt32 * ); + +extern void MapDisk( UInt32, Boolean ); +extern void UnmapDisk( void ); + +extern void WriteDiskChecksum( void ); +extern void MakeDiskChecksum( Ptr in, Ptr out ); +extern void MakeChecksum( Ptr in, Ptr out, UInt32 side, int dimensions ); +extern void CorrectDisk( Ptr, Ptr, Ptr, UInt32, int ); + + +extern void PrintHex( UInt32, int ); +void PrintHex( UInt32 num, int size ) { + char out[8]; + int ccnt = size; + + while ( ccnt-- > 0 ) { + int nibble; + + nibble = ( num >> ( ccnt * 4 ) ) & 0xf; + out[7-ccnt] = (nibble<10)? nibble+'0' : nibble-10+'a'; + } + + ISDebugText( (UInt8 *) out + 8 - size, size ); +} + + +extern pascal OSErr main() { + OSErr err = noErr; + SInt16 myRN; + Boolean diskInited; + SInt32 dl; + + EnterCodeResource(); + + InitInterruptSafeDebug(); + ISDebugStr( "\pRAMB05" ); + + if ( GetToolTrapAddress( 0xabe9 ) == GetToolTrapAddress( _Unimplemented ) ) err = paramErr; + + if ( err == noErr ) { + OSErr gerr; + gerr = Gestalt( '¨mb0', &dl ); + + if ( gerr == noErr ) { + ISDebugStr( "\pRAMBoot: deferred by Gestalt" ); + err = paramErr; + + } else err = NewGestalt( '¨mb0', &GestaltProc ); + } + + if ( err == noErr ) { + RegEntryID chosenRE; + + RegistryEntryIDInit( &chosenRE ); + + { + err = RegistryCStrEntryLookup( NULL, gTreeChosen, &chosenRE ); + } + + if ( err == noErr ) { + err = RegistryPropertyGetSize( &chosenRE, gPhysRunsProp, &gNumRuns ); + + if ( err ) ISDebugStr( "\pRAMBoot: RAM disk space not reserved. Please reinstall." ); + } + + if ( err == noErr ) { + gRuns = (PhysRun *) NewPtrSys( gNumRuns ); + err = MemError(); + } + + if ( err == noErr ) { + int rcnt; + + err = RegistryPropertyGet( &chosenRE, gPhysRunsProp, gRuns, &gNumRuns ); + gNumRuns /= sizeof( PhysRun ); + + for ( rcnt = 0; rcnt < gNumRuns; rcnt++ ) { + gRuns[rcnt].startPage /= 0x1000; + } + + for ( rcnt = 0; rcnt < gNumRuns; rcnt++ ) { + gActualSize += gRuns[rcnt].numBytes; + } + } + + RegistryEntryIDDispose( &chosenRE ); + } + + if ( err == noErr ) { + gWindowStor = NewPtrSys( kPageSize * 4 - 1 ); // 3 pages + padding + err = MemError(); + + if ( err == noErr ) { + gDiskWindowPtr = (Ptr) ( ( (UInt32) gWindowStor + kPageSize-1 ) & kPageBits ); + LockMemory( gDiskWindowPtr, kPageSize * 3 ); + gWindowPage = (UInt32) gDiskWindowPtr / kPageSize; + PrintHex( gWindowPage, 8 ); + + gSumWindowPtr = gDiskWindowPtr + kPageSize; + gSum2WindowPtr = gSumWindowPtr + kPageSize; + } + + if ( err == noErr ) { + PhysRun *lastRun = &gRuns[gNumRuns-1]; + UInt32 sumSize, sum2Size; + + #define PaddedSumSize( x ) ( ( ( ( ( x + kPageSize-1 ) / kPageSize ) * kSumBytesPerPage ) + kPageSize-1 ) & kPageBits ) + + sumSize = PaddedSumSize( gActualSize - ( gActualSize / kSumRatio ) ); + sum2Size = PaddedSumSize( sumSize ); + + gActualSize -= sumSize + sum2Size; + lastRun->numBytes -= sumSize + sum2Size; + + gSumBase = ( lastRun->startPage * kPageSize ) + lastRun->numBytes; + gSum2Base = gSumBase + sumSize; + + gSum3Size = ( sum2Size / kPageSize ) * kSumBytesPerPage;// PaddedSumSize( sum2Size ); + gSum3StrSize = gSum3Size * 2; + PrintHex( gSum3StrSize, 4 ); + + #undef PaddedSumSize + } + + if ( err == noErr ) { + RegistryEntryIDInit( &gOptionsEntry ); + + if ( err == noErr ) { + err = RegistryCStrEntryLookup( NULL, gTreeOptions, &gOptionsEntry ); + } + + if ( err == noErr ) { + gSum3Ptr = NewPtrSysClear( gSum3Size ); + err = MemError(); + } + + if ( err == noErr ) { + gSum3Str = NewPtrSysClear( gSum3StrSize ); + err = MemError(); + } + + if ( err == noErr ) { + UInt32 actSize = gSum3StrSize; + err = RegistryPropertyGet( &gOptionsEntry, gSumPropertyName, gSum3Str, &actSize ); + + if ( err==noErr && actSize != gSum3StrSize ) { + ISDebugStr( "\pSum3 size changed?!" ); + PrintHex( actSize, 4 ); + } + } + + if ( err == noErr ) { + int bcnt; + Ptr pen = gSum3Str; + + for ( bcnt = 0; bcnt < gSum3Size; bcnt++ ) { + int nibble = *pen++; + nibble -= nibble>='a'? 'a'-10 : '0'; + gSum3Ptr[bcnt] = nibble << 4; + + nibble = *pen++; + nibble -= nibble>='a'? 'a'-10 : '0'; + gSum3Ptr[bcnt] |= nibble; + } + } + + if ( err == nrNotFoundErr ) { + err = noErr; + diskInited = false; + ISDebugStr( "\pRAMBoot: Master checksum not found. RAM disk data may be damaged." ); + } else diskInited = true; + } + } + + if ( err == noErr /*&& diskInited*/ ) { + UInt32 bcnt; + char badSum[ kSumBytesPerPage ]; + + UnmapDisk(); + + if ( diskInited ) { + ISDebugStr( "\pCorrecting checksum l2" ); + for ( bcnt = 0; bcnt < gActualSize; bcnt += kPageSize * kSumRatio * kSumRatio ) { + MapDisk( bcnt, true ); + + MakeDiskChecksum( gSum2WindowPtr, badSum ); + PrintHex( *(UInt32*) gCurSum3Ptr, 8 ); + PrintHex( *(UInt32*) badSum, 8 ); + CorrectDisk( gSum2WindowPtr, gCurSum3Ptr, badSum, kSumBoxSide, kSumBoxDimensions ); + + UnmapDisk(); + } + } + + ISDebugStr( "\pCorrecting checksum l1" ); + for ( bcnt = 0; bcnt < gActualSize; bcnt += kPageSize * kSumRatio ) { + MapDisk( bcnt, true ); + + MakeDiskChecksum( gSumWindowPtr, badSum ); + CorrectDisk( gSumWindowPtr, gCurSum2Ptr, badSum, kSumBoxSide, kSumBoxDimensions ); + + UnmapDisk(); + } + + ISDebugStr( "\pCorrecting disk" ); + for ( bcnt = 0; bcnt < gActualSize; bcnt += kPageSize ) { + MapDisk( bcnt, true ); + + MakeDiskChecksum( gDiskWindowPtr, badSum ); + PrintHex( *(UInt32*) badSum, 8 ); + CorrectDisk( gDiskWindowPtr, gCurSumPtr, badSum, kSumBoxSide, kSumBoxDimensions ); + + UnmapDisk(); + } + } + + if ( err == noErr ) { + gActualSize /= 512; + err = TradInstallDriverFromPtr( (DRVRHeaderPtr) &DriverHeader, 48, 127, &myRN ); + } + + if ( err == noErr ) { + ISDebugStr( "\pinstalled drvr" ); + err = OpenDriver( "\p.RAMB0", &myRN ); + } + + if ( err == noErr ) { // find the boot drive & link in after it + gMyDQE.flags[0] = 0; // unlocked + gMyDQE.flags[1] = 8; // nonejectable + gMyDQE.flags[2] = 0; // reserved + gMyDQE.flags[3] = 0; // n/a + gMyDQE.dqe.dQDrive = MoreFindFreeDriveNumber( 8 ); + gMyDQE.dqe.dQRefNum = myRN; + gMyDQE.dqe.dQFSID = 0; + gMyDQE.dqe.qType = 1; + gMyDQE.dqe.dQDrvSz = (UInt16) gActualSize; + gMyDQE.dqe.dQDrvSz2 = (UInt32) gActualSize >> 16; + + Enqueue( (QElemPtr) &gMyDQE.dqe, GetDrvQHdr() ); + + if ( /*!LMGetBootDrive() &&diskInited */true ) { + ISDebugStr( "\pSet boot" ); + LMSetBootDrive( gMyDQE.dqe.dQDrive ); + } + ISDebugStr( "\pLoaded drvr" ); + } + + ExitCodeResource(); + + return noErr; +} + + +asm void DriverHeader() { + dc.w dNeedLockMask | dStatEnableMask | dCtlEnableMask | dReadEnableMask | dWritEnableMask | dNeedTimeMask + dc.w 0 // delay + dc.w 0 // evt mask + dc.w 0 // menu + + dc.w 0x1a + dc.w 0x1e + dc.w 0x28 + dc.w 0x32 + dc.w 0x3c + + dc.b "\p.RAMB0" + +@open: + jmp DriverOpen +@prime: + movem.l a0/a1, -(sp) + jsr DriverPrime + bra.s @finish +@control: + movem.l a0/a1, -(sp) + jsr DriverControl + bra.s @finish +@status: + movem.l a0/a1, -(sp) + jsr DriverStatus + bra.s @finish +@close: + jmp DriverClose + +@finish: + movem.l (sp)+, a0/a1 + move.w 6 (a0), d1 // PB.ioTrap + btst # noQueueBit, d1 + bne.s @rtn + + move.l 0x8fc, -(sp) // jIODone + +@rtn: + move.w d0, 0x10 (a0) // PB.ioResult + rts +} + + +extern OSErr DriverOpen() { + return noErr; +} + + +extern OSErr DriverPrime( IOParamPtr pb:__a0, DCtlPtr dce:__a1 ) { + OSErr err = noErr; + UInt32 ioPen; + int bcnt; + + EnterCodeResource(); + //ISDebugStr( ( pb->ioTrap & 0xff ) == aRdCmd? "\pR" : (/*Debugger(),*/ "\pW") ); + + pb->ioActCount = 0; + + while ( pb->ioActCount < pb->ioReqCount ) { + UInt32 maxTrans, actTrans; + Ptr disk, buff; + Boolean read; + + read = ( pb->ioTrap & 0xff ) == aRdCmd; + ioPen = dce->dCtlPosition + pb->ioActCount; + + MapDisk( ioPen, !read ); + + maxTrans = kPageSize - ( ioPen & (kPageSize-1) ); + actTrans = pb->ioReqCount - pb->ioActCount; + actTrans = (maxTransioBuffer + pb->ioActCount; + + //PrintHex( actTrans, 4 ); + //PrintHex( ioPen, 8 ); + //PrintHex( gRuns[bcnt].startPage + ( ioPen >> 12 ), 5 ); + //ISDebugText( (UInt8*) disk, 200 ); + //ISDebugText( (UInt8*) buff, 4 ); + + if ( read ) { + BlockMoveData( disk, buff, actTrans ); + } else { + BlockMoveData( buff, disk, actTrans ); + WriteDiskChecksum(); + } + + UnmapDisk(); + + pb->ioActCount += actTrans; + } + //ISDebugStr( "\pDone" ); + if ( err ) ISDebugStr( "\p(err)" ); + ExitCodeResource(); + return err; +} + + +extern OSErr DriverControl( CntrlParamPtr pb:__a0, DCtlPtr dce:__a1 ) { + OSErr err; + + EnterCodeResource(); + //ISDebugStr( "\pC" ); + + switch( pb->csCode ) { + case kFormat: { + { + gSum3Ptr = NewPtrSysClear( gSum3Size ); + err = MemError(); + + if ( err == noErr ) { + RegistryPropertyDelete( &gOptionsEntry, gSumPropertyName ); + err = RegistryPropertyCreate( &gOptionsEntry, gSumPropertyName, gSum3Ptr, gSum3Size ); + } + } + + if ( err == noErr ) { + UInt32 pcnt, lcnt; + + for ( pcnt = 0; pcnt < gActualSize * 512; pcnt += kPageSize ) { + MapDisk( pcnt, true ); + for ( lcnt = 0; lcnt < kPageSize; lcnt += sizeof(long) ) * (UInt32 *) &gDiskWindowPtr[lcnt] = 0; + UnmapDisk(); + } + + for ( pcnt = 0; pcnt < gActualSize * 512; pcnt += kPageSize * kSumRatio ) { + MapDisk( pcnt, true ); + for ( lcnt = 0; lcnt < kPageSize; lcnt += sizeof(long) ) * (UInt32 *) &gSumWindowPtr[lcnt] = 0; + UnmapDisk(); + } + + for ( pcnt = 0; pcnt < gActualSize * 512; pcnt += kPageSize * kSumRatio * kSumRatio ) { + MapDisk( pcnt, true ); + for ( lcnt = 0; lcnt < kPageSize; lcnt += sizeof(long) ) * (UInt32 *) &gSum2WindowPtr[lcnt] = 0; + UnmapDisk(); + } + + } + break; + } + case kVerify: + err = noErr; + break; + case accRun: + err = PostEvent( diskEvt, gMyDQE.dqe.dQDrive ); + dce->dCtlFlags &= ~dNeedTimeMask; + break; + default: + PrintHex( pb->csCode, 4 ); + err = controlErr; break; + } + + ExitCodeResource(); + return err; +} + +extern OSErr DriverStatus( CntrlParamPtr pb:__a0, DCtlPtr dce:__a1 ) { + OSErr err; + + EnterCodeResource(); + //ISDebugStr( "\pS" ); + + switch( pb->csCode ) { + case kReturnFormatList: + pb->csParam[0] = 1; + (* (UInt32 **) &pb->csParam[1])[0] = gActualSize; + (* (UInt32 **) &pb->csParam[1])[1] = 0; + err = noErr; break; + default: + PrintHex( pb->csCode, 4 ); + err = statusErr; break; + } + + ExitCodeResource(); + return err; +} + +extern OSErr DriverClose() { + return noErr; +} + +extern pascal OSErr GestaltProc( UInt32, SInt32 *resp ) { + *resp = 0; + return noErr; +} + + +extern void MapDisk( UInt32 pos, Boolean sumToo ) { + { + int bcnt; + UInt32 pen; + + for ( bcnt = 0, pen = pos; bcnt < gNumRuns && gRuns[bcnt].numBytes <= pen; bcnt++ ) { + pen -= gRuns[bcnt].numBytes; + } + if ( bcnt == gNumRuns ) { + return; + } + + VMMap( gWindowPage, gRuns[bcnt].startPage + ( pen / kPageSize ) ); + } + + if ( sumToo ) { + UInt32 sumPos, sum2Pos; + { + sumPos = ( pos / kPageSize ) * kSumBytesPerPage; + gCurSumPhys = gSumBase + sumPos; + + VMMap( gWindowPage + 1, gCurSumPhys / kPageSize ); + gCurSumPtr = gSumWindowPtr + ( gCurSumPhys & (kPageSize-1) ); + } + + { + sum2Pos = ( sumPos / kPageSize ) * kSumBytesPerPage; + gCurSum2Phys = gSum2Base + sum2Pos; + + VMMap( gWindowPage + 2, gCurSum2Phys / kPageSize ); + gCurSum2Ptr = gSum2WindowPtr + ( gCurSum2Phys & (kPageSize-1) ); + } + + { + gCurSum3Ptr = gSum3Ptr + ( sum2Pos / kPageSize ) * kSumBytesPerPage; + } + } +} + +extern void UnmapDisk( void ) { + VMUnmap( gWindowPage, 0 ); + VMUnmap( gWindowPage + 1, 0 ); + VMUnmap( gWindowPage + 2, 0 ); +} + + +extern void WriteDiskChecksum( void ) { + OSErr err; + + MakeDiskChecksum( gDiskWindowPtr, gCurSumPtr ); + MakeDiskChecksum( gSumWindowPtr, gCurSum2Ptr ); + MakeDiskChecksum( gSum2WindowPtr, gCurSum3Ptr ); + + { + int bcnt; + + for ( bcnt = 0; bcnt < gSum3Size; bcnt++ ) { + int nibble; + + nibble = ( gSum3Ptr[bcnt] >> 4 ) & 0xf; + gSum3Str[bcnt * 2] = nibble>9? 'a'-10 : '0'; + gSum3Str[bcnt * 2] += nibble; + + nibble = gSum3Ptr[bcnt] & 0xf; + gSum3Str[bcnt * 2 + 1] = nibble>9? 'a'-10 : '0'; + gSum3Str[bcnt * 2 + 1] += nibble; + } + + err = RegistryPropertySet( &gOptionsEntry, gSumPropertyName, gSum3Str, gSum3StrSize ); + } + + if ( err == noErr ) { + err = RegistryPropertySetMod( &gOptionsEntry, gSumPropertyName, kRegPropertyValueIsSavedToNVRAM ); + } + + if ( err ) { + ISDebugStr( "\pcouldn't write nvsum" ); + PrintHex( err, 4 ); + } +} + +extern void MakeDiskChecksum( Ptr in, Ptr out ) { + MakeChecksum( in, out, kSumBoxSide, kSumBoxDimensions ); +} + +extern void MakeChecksum( Ptr data, Ptr sumPtr, UInt32 side, int dimensions ) { + int underBits, overBits, overStart, dcnt, sum; + UInt32 underCount, overCount, ucnt, ocnt, lcnt, loff, off; + + underBits = 0; + overBits = kSumBoxVolumeLog2 - kSumBoxSideLog2; + + for ( dcnt = 0; dcnt < dimensions; dcnt++ ) { + underCount = 1 << underBits; + overCount = 1 << overBits; + overStart = underBits + kSumBoxSideLog2; + + for ( lcnt = 0; lcnt < kSumBoxSide; lcnt++ ) { + sum = 0; + loff = lcnt << underBits; + + for ( ocnt = 0; ocnt < overCount; ocnt++ ) { + off = loff + ( ocnt << overStart ); + for ( ucnt = 0; ucnt < underCount; ucnt++ ) { + sum ^= data[ off + ucnt ]; + } + } + *sumPtr++ = sum; + } + + underBits += kSumBoxSideLog2; + overBits -= kSumBoxSideLog2; + } +} + + +extern void CorrectDisk( Ptr data, Ptr good, Ptr check, UInt32 side, int dimensions ) { + int dcnt; + UInt32 bcnt; + UInt8 bad = 0; + + for ( bcnt = 0; bcnt < side; bcnt++ ) { + if ( good[bcnt] != check[bcnt] ) { +// if ( bad & (good[bcnt]^check[bcnt]) ) ISDebugStr( "\pToo many errors" ); + bad |= good[bcnt] ^ check[bcnt]; + } + //PrintHex( good[bcnt], 2 ); + //PrintHex( check[bcnt], 2 ); + } + + if(bad)PrintHex( bad, 2 ); + + while ( bad ) { + UInt32 coords[ kMaxDimensions ]; + int cubex = bad & -bad; // what's bad & -bad? Bitwise arithmetic! Oh god it's 3:50 am. + bad ^= cubex; + + for ( dcnt = 0; dcnt < dimensions; dcnt++ ) { + Ptr gcr = &good[dcnt*side], ccr = &check[dcnt*side]; // good/check coordinate row + coords[dcnt] = -1; + + for ( bcnt = 0; bcnt < side; bcnt++ ) { + if ( ( gcr[bcnt] ^ ccr[bcnt] ) & cubex ) { + if ( coords[dcnt] != -1 ) { + ISDebugStr( "\px" ); + coords[dcnt] = -1; + break; + } + coords[dcnt] = bcnt; + } + } + + if ( coords[dcnt] == -1 ) { + //ISDebugStr( "\p?" ); + break; + } + } + + if ( dcnt != dimensions ) continue; // from above break; + + { + UInt32 off = 0; + UInt32 dcoeff = 1; + for ( dcnt = 0; dcnt < dimensions; dcnt++ ) { + off += dcoeff * coords[dcnt]; + dcoeff *= side; + } + + PrintHex( ( data[off] & cubex ) != 0, 1 ); + + data[off] ^= cubex; + } + } +} \ No newline at end of file diff --git a/Patch Partition/Ephemerboot.mcp b/Patch Partition/Ephemerboot.mcp new file mode 100755 index 0000000..07187cf Binary files /dev/null and b/Patch Partition/Ephemerboot.mcp differ diff --git a/Patch Partition/EphemerbootPatch.rsrc b/Patch Partition/EphemerbootPatch.rsrc new file mode 100755 index 0000000..e69de29 diff --git a/Read Me Second.txt b/Read Me Second.txt new file mode 100755 index 0000000..d6b8a87 --- /dev/null +++ b/Read Me Second.txt @@ -0,0 +1 @@ +Ephemerboot 1.0 David "Potatoswatter" Krauss, 5/02 See bottom for credits. What is Ephemerboot? Ephemerboot is a RAM disk driver which will boot Classic on NewWorld machines. Why is it cool? Ephemerboot solves two tough problems, making it Weird. 1. Bit rot Many Macs in the past have been able to boot from RAM disks, allowing very fast startup. However, NewWorld machines (ones since the original iMac, without ROMs) can't. They power down (more accurately, cease to refresh) RAM momentarily during reboot, causing its data to become suddenly ephemeral. It simply fades away... but actually most remains intact. To allow bootable RAM disks despite this, Ephemerboot implements data checksumming & correction to retrieve data lost from RAM transistors to "bit rot". 2. No access The bootability feature of Apple's own RAM disk driver (".EDisk") is hard-coded into the Mac boot sequence. Older machines store it in ROM; NewWorld machines have it in the "Mac OS ROM" file. Before the Mac OS reads anything from disk, ROM code reserves memory for the RAM disk, loads the driver, and takes a special look at it to give it special booting privileges. Only problem is, I don't work at Apple. I was a toddler when that code was written. To accomplish what that little bit of ROM code does, Ephemerboot uses two off-beat components: a chaining bootloader and a patch partition module. A driver in the patch partition module does the real work. 2a. The bootloader The bootloader phase ("ramboot") reserves RAM for the disk. As Open Firmware is running, the Mac represents the arrangement of DIMMs on the motherboard as a set of numbers (starting address/# bytes) in the /memory device-tree node. Ramboot alters these in a way similar to that described in QA1099 [1], with a few differences. Ramboot supports a variable amount of RAM shrinkage. Ramboot supports discontiguous physical memory. This is a bit technical to explain here, but it makes things a hassle to do properly. Unlike the QA1099 method, RAMBoot isn't designed simply to waste RAM. It reclaims 2 MB of memory that would otherwise be wasted because it's used by Open Firmware. To see your reclaimed memory, go to Apple System Profiler and look at the "Memory" section. Ramboot allows the user to choose where memory gets allocated from. This feature was hacked onto the preceding one. Note that physical addresses don't actually correspond to DIMMs when interleaving is used. DRAM interleaving allows RAM chips to act in parallel, which is normally good. It happens when you have two DIMMs of identical size in adjacent slots. 2b. The patch partition module The patch partition module contains the actual Classic Mac OS driver. (Nearly) every partitionable disk has a patch partition, an obscure and little-used invisible 256 kB partition. Code from this partition is loaded and run at boot. Normally this does boring things like patch ROM disk drivers from the pre-4 GB era and allow machines predating popular CD-ROM drives to boot from them with the "c" key. Actually, that's all that patch partitions have ever done, far as I know. You might have noticed, however, that these functions both deal with letting the machine boot from things it normally wouldn't. That's because the patch partition is run before the boot volume is determined. The patch partition consists of a series of modules in a grow-down stack and a series of module descriptions in a grow-up stack. The Ephemerboot Installer adds its code to both stacks. ----------- patch partition description 1 description 2 Ephemerboot description - empty space - Ephemerboot code patch 2 patch 1 ------------ / 256k The patch code is generated from a single source file, Ephemerboot.c. It first loads from the Name Registry information from the bootloader stage about where the disk is located. If that succeeds, it loads the master checksum from NVRAM and performs the data correction. Then, it loads the driver and the disk. 2c. The driver The driver is as simple as Mac disk drivers get. It's synchronous and it does I/O with BlockMoveData(). It's not that simple, tho. Once some physical memory has been cordoned off in Open Firmware, it's tough to access. It's so well-hidden that not even the Nanokernel knows about it Ñ just trying to read those addresses causes a crash (an unmapped memory exception). No public Mac API will bring that memory back. However, there's a cute little app called PowerMacInfo, written as a kernel monitoring tool by some really cool Apple engineers. It can show you physical memory at any address. (By default, it only shows you memory the kernel knows about, but it can be fooled with MacsBug.) So I reverse-engineered it. It's the "old-style" 68k VM interface. It centers around opword 0xfe0a (that's an f-trap!). The definitions at the top of EphermerBoot.c should be a good enough explanation. The second parameter to VMUnmap controls whether the page should be remapped upon an unmapped access (true) or if unmapped accesses should cause a propagated fault (false). The parameters are UInt32's because they're page numbers, not addresses. VMMap/VMUnmap are used to create windows in memory through which the disk and checksums are accessed. Three windows exist for two checksums and the disk. While the disk is not being used, the window pages are set to propagate exceptions. Since they're low in system memory, this can cause MacsBug to complain (especially on "hc all"). If you don't like it, you have the source. Checksums are created with every write operation. It's set up so that 32 bytes of checksum check every page (4096 bytes) of memory. Even at this ratio (1:128), the checksums are pretty big. To store a top-level checksum in nonvolatile RAM, which is preserved across restarts but is very small, I had to use 3 levels. The first two can be large and are accessed by floating VM windows; the third is a regular block in the system heap which gets stored by Name Registry calls at every write op. The end effect of calculating 3 large checksums in 68k code, and then saving to slow NVRAM, is that the RAM disk is slowed to the speed of a regular hard drive (on my 333MHz Lombard anyway). I'm sorry about this. Not like anyone can actually install it ;v) . How do I install it? It's unlikely that you can. However, if you'd like to try, follow these instructions. - Update your firmware from apple.com. - Copy "ramboot" to the root directory of your internal ATA drive. - Copy "install.f" to the root directory of same drive. - Double-click the installer & drag a hard-drive icon onto it. - Turn startup memory tests off with the Memory control panel (cmd-opt to see the option). - Reboot and immediately hold down cmd-opt-O-F to get into Open Firmware. - Type boot hd:,\install.f to automatically set your boot environment variables. (That's colon-comma, not a semicolon.) If you want a disk size other than 64MB, do setenv ramboot-disk-size xxx00000 where xxx is the size in MB of the disk. - Hit the power button (or eject key) to shut down, then again to start up again. The machine should boot into Mac OS. You should get some status messages and get a disk init box. - Name & format the disk. - Install system software to it. If you use the actual Apple installer application, be sure to disable updating disk drivers. - Copy the "Mac OS ROM" file from the RAM disk system folder to the same root dir as "ramboot". - Set the type of that ROM file from 'tbxi' to 'tbxj'. It'll lose it's icon. If having it there is too freaky 4 U, rename it too. - Unbless your selected system folder by removing the System or Finder, if it's on the same volume as the tbxj. - Reboot. The machine should now boot from the RAM disk! Note that this has only run on the single test machine it was written for. Although no single reason it wouldn't work has been isolated, there appear to be many reasons it doesn't. The test machine is a Lombard PowerBook. So far (at MacHack) it hasn't worked on 2 Pismos (with mutually exclusive sets of problems), a slot-loading iMac, a Sunflower iMac, and a QuickSilver G4. How do I uninstall it? Very luckily, this is easier. - Use Drive Setup to update the driver on the disk you installed it onto. - In Open Firmware, do setenv boot-command mac-boot bye - If you're really hopping mad at me and you want to wipe all traces of this consarned program from your machine, reset NVRAM by restarting and holding down cmd-opt-P-R through a couple chimes. How do I recompile it? The Ephemerboot.mcp project only builds the executable code Ñ you still need to get that & a patch description into the installer. Open BuildpDES.mcp and hit "Run". It'll rebuild & run the installer builder. You can then use the installer to write over old versions. Nota bene disclaimer cuidado: Patch partitions can be extremely dangerous. If you call Debugger(), you won't be able to boot from that disk. If you do something that crashes no matter what, you'll probably have to use OS X's disk utility to update the drivers. Let's just be thankful OS X is there. The installer app is based on an internal app from my company. You can't have the source to the disk stuff. If you like the shell tho (it actually supports things like actual strings and icons and dropping stuff on the Finder icon), you can get it at http://homepage.mac.com/potswa/source/StandardDropin.sit. How'd ya do it? Who helped? First off, I couldn't have done this without the help of these helpful helpers: Miro (meeroh) Jurisic went out & spent a MacHack on this. Imagine going through that install sequence over and over and over and over and over (except without the install.f file), with great programmers having great fun all around you. Thank you meeroh! RenŽ Vega helped a bit with VM and suggested bit rot would be a problem before anything ran. Prolly woulda given up otherwise. Also he wrote much of PowerMacInfo in the first place. Quinn "The Eskimo!" for his wonderful InterruptSafeDebug and TradDriverLoaderLib. MoreDisks is also great, tho I don't use it much in here. Quinn also introduced me to discontiguous physical memory. Seeing as my machines all have contiguous memory, I don't think I'd have caught that. I wrote this because I wanted to use my patch partition, driver, and bootloader l337 sk1llz on something fun. After reading [1] and seeing PowerMacInfo in action, I knew it was possible. The toughest part was reverse-engineering PowerMacInfo. Early on, I tried to make the project more ambitious by doing it without the patch partition. I tried to do a hack System file that would load the driver, then unload itself and change the boot drive. I got pretty far along Ñ the ROM would reload the real System file, but the second call to InitResources() would always fail. I gave up on that, but the source is included here as MegaBoot.c. That file also includes a really neat a-trap tracer based on ISDebug. After that, the checksumming took a couple tries to get right. I hadn't expected to do it at the outset, but in the end I think it's cooler than just getting through the Mac OS tangle. After I decided to use the patch partition, Ephemerboot took about 10 days to implement. Reference [1] Apple Technical Q&A QA1099: Reducing the size of Physical Memory in Open Firmware. http://developer.apple.com/qa/qa2001/qa1099.html Revisions 6/20/02 - 1.0 - Doc written for MacHack. \ No newline at end of file diff --git a/machack speech.txt b/machack speech.txt new file mode 100755 index 0000000..3d6efc0 --- /dev/null +++ b/machack speech.txt @@ -0,0 +1 @@ +Unfortunately, do to problems with installing on the demo machines at MacHack, and my physical location in New York (I had to do some high-school exams on 6/21), Ephemerboot was not presented at the Hack Show. It didn't get voted on & wasn't eligible for awards - here on the CD is its initial introduction. As part of a last-ditch effort to be allowed to present, I wrote this speech script (during the hack show, but in New York). This covers the more interesting bits of the project faster than the Read Me, and also covers some stuff the other file doesn't, so I suggest reading it first. Special thanks to Miro Jurisic (author of the 1998 winning Hack) for his hurculean efforts trying to install Ephemerboot on about a million different Macs, and to get a presentation slot. ----- Hello, I'm Dave Krauss, and I'm gonna tell you about the hack Ephemerboot. Ephemerboot is a bootable RAM disk driver for NewWorld Macs. To boot a newworld mac from ram, a few difficulties must be overcome. Data must be retrieved from powered-off RAM chips; Virtual Memory must be mercilessly hacked; and unspeakable evils must be perpetrated in the Forth level of Open Firmware hell. Machines since the iMac stop maintaining their dimms for a fraction of a second during reboot. During the missed refresh cycles, data fades away, a process called "bit rot". But not everything is erased. Just as human memory can be ephemeral, so is the ram of a newworld mac at reboot. hence ephemerboot. To eliminate bit rot, I implemented a data checksumming and recovery scheme. When the Mac powers up, it reads the checksums and uses them to correct the rotten bits, which luckily occur one at a time. The checksum is also stored in ram, tho. So it's a good idea to checksum the checksum. Then I checksum that checksum again, and that one's small enough to be flashed to nonvolatile ram where it's safe. So, the driver writes 3 checksums with every write. Next is the problem of allocating memory in a way that it's safe even through a reboot. That has to be done in Open firmware. A bootloader script erases the Mac's automatically-generated description of its ram chips, and replaces it with a new one. Data is safe in chips the Mac OS doesn't know it has. This also gets around basic limitations in the Mac OS, like the 1.5 gig limit. A 500 meg Ephboot disk should let a 2 gig machine use all of its memory. But if the operating system doesn't know about the memory, how will the driver access it? Normally, the OS controls the gate between the pointers we know and the chips. There is no published Apple API that allows us to use physical ram. So I reverse-engineered an obscure Apple utility that lets you look at physical memory. There are just two calls to the mini-api, which let you access any memory in the machine, including PowerPC interrupt vectors. This is powerful stuff - see the source code. Finally, there's the problem of how to load the driver early enough to boot from it. Obviously an extension won't do. Ephemerboot installs code into your disk's patch partition, where it's executed really early. I don't have time to talk about patch partitions, but they're not very well documented either. What I can tell you is that the source on the CD will include a little utility for you to write your own patch partitions. Maybe some of you can use it to keep the tradition of hacking 9 alive. \ No newline at end of file