initial
This commit is contained in:
commit
1f23cecf7f
|
@ -0,0 +1,492 @@
|
|||
#include <InterruptSafeDebug.h>
|
||||
#include <TradDriverLoaderLib.h>
|
||||
#include <A4Stuff.h>
|
||||
|
||||
#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 = (maxTrans<actTrans)? maxTrans : actTrans;
|
||||
|
||||
disk = (Ptr) ( gWindowPage << 12 ) + ( ioPen & 0xfff );
|
||||
buff = pb->ioBuffer + 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;
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
<CHRP-BOOT>
<COMPATIBLE>
MacRISC
</COMPATIBLE>
<DESCRIPTION>
Pre-bootloader clips visible RAM to allocate a RAM disk.
</DESCRIPTION>
<BOOT-SCRIPT>
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
</BOOT-SCRIPT>
</CHRP-BOOT>
|
|
@ -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
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,49 @@
|
|||
//BuildpDES.c
|
||||
//©5/18/02 David "Potatoswatter" Krauss
|
||||
|
||||
#include <SCSI.h>
|
||||
|
||||
|
||||
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" );
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,698 @@
|
|||
//RAMBoot.c - boot 9 from RAM.
|
||||
//©5/18/02 - 5/27/02 David "Potatoswatter" Krauss - v1.0.0c1
|
||||
|
||||
#include <InterruptSafeDebug.h>
|
||||
#include <TradDriverLoaderLib.h>
|
||||
#include <MoreDisks.h>
|
||||
#include <A4Stuff.h>
|
||||
|
||||
#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 = (maxTrans<actTrans)? maxTrans : actTrans;
|
||||
|
||||
disk = gDiskWindowPtr + ( ioPen & 0xfff );
|
||||
buff = pb->ioBuffer + 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;
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
File diff suppressed because one or more lines are too long
|
@ -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.
|
Loading…
Reference in New Issue