diff --git a/IM-D ParamBlock diagram b/IM-D ParamBlock diagram new file mode 100644 index 0000000..2e203c3 --- /dev/null +++ b/IM-D ParamBlock diagram @@ -0,0 +1,8 @@ + + + + + URL + http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/Devices/Devices-13.html + + diff --git a/NetBoot.py b/NetBoot.py index afe2eaf..7e71f2d 100755 --- a/NetBoot.py +++ b/NetBoot.py @@ -4,8 +4,464 @@ # Adapted from: http://chaos.weblogs.us/archives/164 import socket +import os +from os import path +import struct -ANY = "0.0.0.0" +import time + + + + +# ; the below code might come in handy later on, when we support executable boot blocks. +# CodeToUncorruptTheBootBlocks: +# move.l (SP),A1 +# sub.l #8,A1 ; What will be the start address of the boot blocks?? + +# lea BigDiskImage,A0 +# move.l #1024,D0 +# dc.w 0xA02E ; BlockMove + +# sub.l #6,(SP) ; Re-run the code that called us; it will be real boot blocks now! +# rts + + + + + + +my_unique_ltoudp_id = b'El' + (os.getpid() & 0xFFFF).to_bytes(2, 'big') + + + +disk_image = open(path.join(path.dirname(path.abspath(__file__)), 'systools607.dsk'), 'rb').read() + + + + +def assemble(the_code): + with open('/tmp/vasm.bootblocks', 'w') as f: + f.write(the_code) + + assembler = path.join(path.dirname(path.abspath(__file__)), 'vasm-1/vasmm68k_mot') + os.system(f'{assembler} -quiet -Fbin -pic -o /tmp/vasm.bootblocks.bin /tmp/vasm.bootblocks') + + with open('/tmp/vasm.bootblocks.bin', 'rb') as f: + return f.read() + + + + +# typedef short (*j_code)( short command, # SP+4 (sign-extend to long) +# DGlobals *g, # SP+8 +# int **var1, # SP+12 +# int **var2); # SP+16 + +# We return our OSErr in d0, and leave the 16 bytes of arguments on the stack for the caller to clean + +image = assemble(f''' +myUnitNum equ 52 +myDRefNum equ ~myUnitNum + + + cmp.l #1,4(SP) + beq getBootBlocks + cmp.l #2,4(SP) + beq getSysVol + cmp.l #3,4(SP) + beq mountSysVol + + move.l #-1,d0 + rts + + +getBootBlocks + lea DiskImage,A0 + move.l 8(SP),A1 ; Inside the global struct... + add.l #$BA,A1 ; ...is an element for the structured part of the boot blocks + move.l #138,D0 ; ...of this length + + dc.w $A02E ; BlockMove + + bra return + + +getSysVol + ; Our register conventions: + ; A2 = fake dqe; A3 = dce; A4 = copied driver + + link A6,#-$32 + movem.l A2-A4/D3,-(SP) + + ; Now I copy all this stuff under BufPtr (because this current location will disappear) + sub.l #(BufPtrCopyEnd-BufPtrCopy),$10C ; BufPtr + move.l $10C,A4 ; ... into A4 + + ; Copy the driver and image as one chunk + lea BufPtrCopy,A0 + move.l A4,A1 + move.l #(BufPtrCopyEnd-BufPtrCopy),D0 + dc.w $A02E ; BlockMove + + ; Install the driver in the unit table + move.l #myDRefNum,D0 + dc.w $A43D ; _DrvrInstall ReserveMem + bne error + + ; Get DCE handle of installed driver + move.l $11C,A0 ; UTableBase + add.l #myUnitNum*4,A0 + move.l (A0),A3 + + ; Lock it down + move.l A3,A0 + dc.w $A029 ; _HLock + + ; Populate the empty DCE that DrvrInstall left us + move.l (A3),A0 ; A0 = dce ptr + + move.l A4,0(A0) ; dCtlDriver is pointer (not hdl) + + move.w 0(A4),D0 ; drvrFlags + and.w #~$0040,D0 ; Clear dRAMBased bit (to treat dCtlDriver as a pointer) + move.w D0,4(A0) ; dCtlFlags + + ; Copy these other values that apparently the Device Mgr forgets + move.w 2(A4),$22(A0) ; drvrDelay to dCtlDelay + move.w 4(A4),$24(A0) ; drvrEMask to dCtlEMask + move.w 6(A4),$26(A0) ; drvrMenu to dCtlMenu + + ; Open the driver + lea -$32(A6),A0 + bsr clearblock + lea DrvrNameString,A1 + move.l A1,$12(A0) ; IOFileName + dc.w $A000 ; _Open + bne error + + ; Attempt to read from the driver +; lea -$32(A6),A0 +; bsr clearblock +; move.w #myDRefNum,$18(A0) ; ioRefNum +; move.l #$200,$24(A0) ; ioByteCount +; dc.w $A002 +; bne error + + ; Create a DQE + move.l #$16,D0 + dc.w $A71E ; _NewPtr ,Sys,Clear + add.l #4,A0 ; has some cheeky flags at negative offset + move.l A0,A2 + + ; Point our caller to the fake dqe + move.l 4+12(A6),A1 + move.l A2,(A1) + + ; Find a free drive number (nicked this code from BootUtils.a:AddMyDrive) + LEA $308,A0 ; [DrvQHdr] + MOVEQ #4,D3 ; start with drive number 4 +CheckDrvNum + MOVE.L 2(A0),A1 ; [qHead] start with first drive +CheckDrv + CMP.W 6(A1),D3 ; [dqDrive] does this drive already have our number? + BEQ.S NextDrvNum ; yep, bump the number and try again. + CMP.L 6(A0),A1 ; [qTail] no, are we at the end of the queue? + BEQ.S GotDrvNum ; if yes, our number's unique! Go use it. + MOVE.L 0(A1),A1 ; [qLink] point to next queue element + BRA.S CheckDrv ; go check it. + +NextDrvNum + ; this drive number is taken, pick another + + ADDQ.W #1,D3 ; bump to next possible drive number + BRA.S CheckDrvNum ; try the new number +GotDrvNum + + ; Populate the DQE + move.l #$80080000,-4(A2) ; secret flags, see http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/Files/Files-112.html + move.w #1,4(A2) ; qType + move.w #(DiskImageEnd-DiskImage)&$FFFF,$C(A2) ; dQDrvSz + move.w #(DiskImageEnd-DiskImage)>>16,$E(A2) ; dQDrvSz2 + move.w #0,$A(A2) ; dQFSID should be for a native fs + + ; Into the drive queue (which will further populate the DQE) + move.l A2,A0 ; A0 = DQE ptr + move.w D3,D0 + swap.w D0 ; D0.H = drive number + move.w #myDRefNum,D0 ; D0.L = driver refnum + dc.w $A04E ; _AddDrive + bne error + + ; Save this most precious knowledge for later + lea gDriveNum,A0 + move.w D3,(A0) + + ; Clean up our stack frame + movem.l (SP)+,A2-A4/D3 + unlk A6 + + bra return + +mountSysVol + link A6,#-$32 + movem.l A2-A4/D3,-(SP) + + lea gDriveNum,A0 + move.w (A0),D3 + + ; Make our call able to work! (Fuck, this is ugly) + lea NaughtyFSQHSave,A0 + move.l $3E2,(A0) + lea NaughtyFSQHKiller,A0 + move.l A0,$3E2 ; Disable FSQueueSync + + ; Try to mount the volume! + lea -$32(A6),A0 + bsr clearblock + + ; FSQueue ourself! +; move.w #$A00F,D1 +; move.l $2AE,A1 ; ROMBase +; add.l #$42E8,A1 +; jsr (A1) + + ; MountVol and pray + move.w #7,$16(A0) ; ioVRefNum = ioDrvNum = the drive number + dc.w $A00F ; _MountVol + + ; Tell Elliot that we made it through + move.w #$1234,D0 + dc.w $a9c9 + + + + + + + + + movem.l (SP)+,A2-A4/D3 + unlk A6 + + bra return + +return + move.l #0,d0 + rts + +error + move.w #$DDDD,D0 + dc.w $A9C9 + + +clearblock + clr.w $0(A0) + clr.w $2(A0) + clr.w $4(A0) + clr.w $6(A0) + clr.w $8(A0) + clr.w $a(A0) + clr.w $c(A0) + clr.w $e(A0) + clr.w $10(A0) + clr.w $12(A0) + clr.w $14(A0) + clr.w $16(A0) + clr.w $18(A0) + clr.w $1a(A0) + clr.w $1c(A0) + clr.w $1e(A0) + clr.w $20(A0) + clr.w $22(A0) + clr.w $24(A0) + clr.w $26(A0) + clr.w $28(A0) + clr.w $2a(A0) + clr.w $2c(A0) + clr.w $2e(A0) + clr.w $30(A0) + rts + + +NaughtyFSQHSave + dc.l 0 + + +NaughtyFSQHKiller + move.l A0,-(SP) + lea NaughtyFSQHSave,A0 + move.l (A0),$3E2 + move.l (SP)+,A0 + + add.l #4,SP + rts + + +DrvrNameString + dc.b 11, ".netRamDisk" + + +gDriveNum + dc.w 0 + + +; code on this side is for start only, and stays in the netBOOT driver globals until released + +BufPtrCopy + +; code on this side gets copied beneath BufPtr (is that the best place??) + + +; Shall we start with a driver? +DrvrBase + dc.w $4F00 ; dReadEnable dWritEnable dCtlEnable dStatEnable dNeedLock + dc.w 0 ; delay + dc.w 0 ; evt mask + dc.w 0 ; menu + + dc.w DrvrOpen-DrvrBase + dc.w DrvrPrime-DrvrBase + dc.w DrvrControl-DrvrBase + dc.w DrvrStatus-DrvrBase + dc.w DrvrClose-DrvrBase + dc.b 11, ".netRamDisk" + +; a0=iopb, a1=dce on entry to all of these... + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +DrvrOpen + move.w #0,$10(A0) ; ioResult + rts + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +DrvrPrime + movem.l A0-A4/D0-D4,-(SP) + move.l A0,A2 ; ParamBlk + move.l A1,A3 ; DCE + + cmp.b #2,$7(A2) ; ioTrap == aRdCmd + bne.s notRead + + ; D0 = number of bytes to read + move.l $24(A2),D0 ; ioReqCount + move.l D0,$28(A2) ; -> ioActCount + + ; D1 = source offset + clr.l D1 + cmp.b #1,$2C(A2) ; ? ioPosMode == fsFromStart + beq.s dontAddMark + add.l $10(A3),D1 ; add dCtlPosition +dontAddMark + cmp.b #3,$2C(A2) ; ? ioPosMode == fsFromMark + bne.s dontAddOffset + add.l $2E(A2),D1 ; add ioPosOffset +dontAddOffset + + ; Advance the pointer + move.l D0,D2 + add.l D1,D2 ; calculate new position + move.l D2,$10(A3) ; -> dCtlPosition + move.l D2,$2E(A2) ; -> ioPosOffset + + ; Do the dirty + lea DiskImage,A0 + add.l D1,A0 + move.l $20(A2),A1 ; ioBuffer + dc.w $A02E ; BlockMove + + move.w #0,$10(A2) ; ioResult + bra primeFinish + + +notRead + move.w #$2222,D0 + dc.w $A9C9 + cmp.b #3,7(A0) ; ioTrap == aRdCmd + + +primeFinish + movem.l (SP)+,A0-A4/D0-D4 + bra DrvrFinish + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +DrvrControl + move.w #$2222,D0 + dc.w $A9C9 + + move.w #0,$10(A0) ; ioResult + bra DrvrFinish + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +DrvrStatus + cmp.w #6,$1A(A0) + beq.s status_fmtLstCode + cmp.w #8,$1A(A0) + beq.s status_drvStsCode + bra.s status_unknown + +status_fmtLstCode ; tell them about our size + move.l A2,-(SP) + move.w #1,$1C(A0) + move.w $1C+4(A0),A2 + move.l #(DiskImageEnd-DiskImage),0(A2) + move.l #$40000000,4(A2) + move.l (SP)+,A2 + + move.w #0,$10(A0) ; ioResult = statusErr + bra DrvrFinish + +status_drvStsCode ; tell them about some of our flags + move.w #0,$1C(A0) ; csParam[0..1] = track no (0) + move.l #80080000,$1C+2(A0) ; csParam[2..5] = same flags as dqe + + move.w #0,$10(A0) ; ioResult = noErr + bra DrvrFinish + +status_unknown + move.w $1A(A0),D0 ; dodgy, for debugging + add.w #$3000,D0 + dc.w $A9C9 + + move.w #-18,$10(A0) ; ioResult + bra DrvrFinish + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +DrvrClose + move.w #$4444,D0 + dc.w $A9C9 + + move.w #0,$10(A0) ; ioResult + rts + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +DrvrFinish + move.w 6(A0),D1 ; iopb.ioTrap + btst #9,D1 ; noQueueBit + bne.s DrvrNoIoDone + move.l $8FC,-(SP) ; jIODone +DrvrNoIoDone + rts + + +DiskImage {chr(10).join(' dc.b ' + str(x) for x in disk_image)} +DiskImageEnd + +BufPtrCopyEnd +''') + + + + +image = image.ljust(512*20) + + +ANY = "0.0.0.0" MCAST_ADDR = "239.192.76.84" MCAST_PORT = 1954 @@ -25,15 +481,223 @@ status = sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(MCAST_ADDR) + socket.inet_aton(ANY)) -# setblocking(0) is equiv to settimeout(0.0) which means we poll the socket. -# But this will raise an error if recv() or send() can't immediately find or send data. -# sock.setblocking(0) + + +# Wrap up in all sorts of crap... +def mk_ddp(dest_node, dest_socket, src_node, src_socket, proto_type, data): + # Wrap into DDP datagram + data = struct.pack('>HBBB', len(data) + 5, dest_socket, src_socket, proto_type) + data + + # Wrap into LLAP packet + data = struct.pack('>BBB', dest_node, src_node, 1) + data + + # Wrap the novel LToUDP header + data = my_unique_ltoudp_id + data + + return data + + + +def pstring(x): + try: + x = x.encode('mac_roman') + except AttributeError: + pass + + return bytes([len(x)]) + x + + while 1: - try: - data, addr = sock.recvfrom(1024) - except socket.error as e: - pass + data, addr = sock.recvfrom(1024) + + # Okay... LToUDP parsing here. Let's start with the LLAP packet. + # Man, chaining protocols is hard. This will inevitably require a rewrite. + # Be careful to keep this as one cascading thing... + + if len(data) < 4: continue + if data.startswith(my_unique_ltoudp_id): continue + data = data[4:] # Trim down to LLAP packet (not "frame") + + if len(data) < 3: continue + llap_dest_node = data[0] + llap_src_node = data[1] + llap_proto_type = data[2] + data = data[3:] # Trim down to LLAP payload + + # Try to extract a DDP header, which is all we want! + if llap_proto_type == 1: + # ddp, short + if len(data) < 5: continue + ddp_len, ddp_dest_socket, ddp_src_socket, ddp_proto_type = struct.unpack_from('>HBBB', data) + data = data[5:ddp_len] + elif llap_proto_type == 2: + # ddp, long (what should we do with this extra information?) + if len(data) < 13: continue + ddp_len, ddp_cksum, ddp_dest_net, ddp_src_net, ddp_dest_node, ddp_src_node, ddp_dest_socket, ddp_src_socket = struct.unpack_from('>4H5B', data) + ddp_hop_count = (ddp_len >> 10) & 0xF + ddp_len &= 0x3FF + data = data[13:ddp_len] else: - print("From: ", addr) - print("Data: ", data) + # llap control packet -- can probably ignore! + continue + + print(f'datagram {llap_src_node}:{ddp_src_socket}->{llap_dest_node}:{ddp_dest_socket}', end=' ') + + if ddp_proto_type == 2: + # Name Binding Protocol + + if len(data) < 2: continue + nbp_func = data[0] >> 4 + nbp_tuple_cnt = data[0] & 0xF + nbp_id = data[1] + data = data[2:] + + nbp_tuples = [] + while data and len(nbp_tuples) < nbp_tuple_cnt: + if len(data) < 5: break + this_tuple = list(struct.unpack_from('>HBBB', data)) + data = data[5:] + for i in range(3): + # This should be coded more defensively, perhaps using exceptions + this_tuple.append(data[1:1+data[0]].decode('mac_roman')) + data = data[1+data[0]:] + nbp_tuples.append(tuple(this_tuple)) + + + print('nbp func', nbp_func, 'id', nbp_id) + for t in nbp_tuples: + print(f' net:node:sock={t[0]}:{t[1]}:{t[2]} enum={t[3]} object:type@zone={t[4]}:{t[5]}@{t[6]}') + + if nbp_func == 2: + # NBP LkUp + + if len(nbp_tuples) == 1 and nbp_tuples[0][5] == 'BootServer': # Looking for us + sock.sendto(mk_ddp( + dest_node=llap_src_node, dest_socket=ddp_src_socket, + src_node=99, src_socket=99, + proto_type=2, + data=bytes([0x31, nbp_id]) + # 3=LkUp-Reply, 1=number-of-tuples + struct.pack('>HBBB', # Pack the first tuple + 0, # (My) Network number + 99, # (My) Node ID + 99, # (My) Socket number + 0, # (My) Enumerator (i.e. which of many possible names for 99/99 is this?) + ) + + pstring(nbp_tuples[0][5]) + pstring('BootServer') + pstring('*') + ), + (MCAST_ADDR, MCAST_PORT)) + + elif ddp_proto_type == 10: + # Mysterious ATBOOT protocol + + if len(data) < 2: continue + boot_type, boot_vers = struct.unpack_from('>BB', data) + data = data[2:] + + # rbNullCommand EQU 0 ; ignore this one + # rbMapUser EQU 1 ; user record request + # rbUserReply EQU 2 ; user record reply + # rbImageRequest EQU 3 ; image request & bitmap + # rbImageData EQU 4 ; image data + # rbImageDone EQU 5 ; server done with current image + # rbUserRecordUpdate EQU 6 ; new user info to server + # rbUserRecordAck EQU 7 ; info received from server + + if boot_type == 1: + # It might be neater to trim off the "type" and "version" fields a bit earlier + boot_machine_id, boot_timestamp, boot_username = struct.unpack_from('>HL 34p', data) + + print(f'atboot type={boot_type}, vers={boot_vers}, machineID={boot_machine_id}, userName={boot_username}') + + # // This defines a user record. + # // Some of these fields can be determined on the fly by the boot server, + # // while others are stored on disk by the boot server + # typedef struct + # { + # char serverName[serverNameLength]; // server name to boot off of + # char serverZone[zoneNameLength]; // and the zone it lives in + # char serverVol[volNameLength]; // the volume name + # short serverAuthMeth; // authentication method to use (none, clear txt, rand) + # unsigned long sharedSysDirID; // dir id of shared system folder + # unsigned long userDirID; // dir id of the user's private system folder + # unsigned long finderInfo[8]; // blessed folder dir id, startup folder dir id etc... + # unsigned char bootBlocks[138]; // see Inside Mac V-135 + # unsigned short bootFlag; // server based flags + # unsigned char pad[306-18]; // pad to ddpMaxData + # }userRecord; + + # // This defines the user record reply sent to workstations. + # typedef struct + # { + # unsigned char Command; /* record or image request command word */ + # unsigned char pversion; /* version of boot protocol spoken by requestor */ + # unsigned short osID; /* type and version of os */ + # unsigned int userData; /* time stamp goes here */ + # unsigned short blockSize; /* size of blocks we will send */ + # unsigned short imageID; /* image ID */ + # short result; /* error codes */ + # unsigned int imageSize; /* size of image in blocks */ + # userRecord userRec; /* tell user where to go */ + # }BootPktRply; + + # Ignore the silly user record. Just make the fucker work! + sock.sendto(mk_ddp( + dest_node=llap_src_node, dest_socket=ddp_src_socket, + src_node=99, src_socket=99, + proto_type=10, + data=struct.pack('>BBHLHHhL', 2, 1, boot_machine_id, boot_timestamp, 512, 0, 0, len(image) // 512).ljust(586, b'\0') + ), + (MCAST_ADDR, MCAST_PORT)) + + elif boot_type == 3: + # It seems to want part of the boot image! + # print('it wants data', data) + + # typedef struct + # { + # unsigned short imageID; /* */ + # unsigned char section; /* "section" of the image the bitmap refers to */ + # unsigned char flags; /* ??? */ + # unsigned short replyDelay; + # unsigned char bitmap[512]; /* bitmap of the section of the image requested */ + # }bir; // Boot Image Req + + print('Boot Image Req') + + if len(data) < 6: continue + boot_image_id, boot_section, boot_flags, boot_reply_delay = struct.unpack_from('>HBBH', data) + data = data[6:] + + # Okay, pretty much just send the bits that were requested! + print('Sending blocks') + for blocknum in range(len(image) // 512): + if len(data) > blocknum // 8 and (data[blocknum // 8] >> (blocknum % 8)) & 1: + # typedef struct { + # unsigned char packetType; /* The command number */ + # unsigned char packetVersion; /* Protocol version number */ + # unsigned short packetImage; /* The image this block belongs to */ + # unsigned short packetBlockNo; /* The block of the image (starts with 1) */ + # unsigned char packetData[512];/* the data portion of the packet */ + # } BootBlock,*BootBlockPtr; + + # print(f' {blocknum}', end='', flush=True) + sock.sendto(mk_ddp( + dest_node=llap_src_node, dest_socket=ddp_src_socket, + src_node=99, src_socket=99, + proto_type=10, + data=struct.pack('>BBHH', 4, 1, boot_image_id, blocknum) + image[blocknum*512:blocknum*512+512] + ), + (MCAST_ADDR, MCAST_PORT)) + + # time.sleep(0.5) + # break # wait for another request, you mofo! + + elif boot_type > 4: + print(f'protocol10 type={boot_type} vers={boot_vers} contents={repr(data)}') + + + + + else: + print('unknown ddp payload', ddp_proto_type) diff --git a/doeverything.bash b/doeverything.bash new file mode 100755 index 0000000..82e53cb --- /dev/null +++ b/doeverything.bash @@ -0,0 +1,5 @@ +#!/bin/bash + +trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT + +./NetBoot.py & cp xo.rom edit.rom && ./xo-rom-enable-netboot.py edit.rom && Mini\ vMac\ Classic.app/Contents/MacOS/minivmac edit.rom && kill %1 diff --git a/systools607.dsk b/systools607.dsk new file mode 100644 index 0000000..3512076 Binary files /dev/null and b/systools607.dsk differ diff --git a/vasm-1/obj/m68k_mot_atom.o b/vasm-1/obj/m68k_mot_atom.o new file mode 100644 index 0000000..6449d0a Binary files /dev/null and b/vasm-1/obj/m68k_mot_atom.o differ diff --git a/vasm-1/obj/m68k_mot_cond.o b/vasm-1/obj/m68k_mot_cond.o new file mode 100644 index 0000000..0527562 Binary files /dev/null and b/vasm-1/obj/m68k_mot_cond.o differ diff --git a/vasm-1/obj/m68k_mot_cpu.o b/vasm-1/obj/m68k_mot_cpu.o new file mode 100644 index 0000000..6366c1a Binary files /dev/null and b/vasm-1/obj/m68k_mot_cpu.o differ diff --git a/vasm-1/obj/m68k_mot_dwarf.o b/vasm-1/obj/m68k_mot_dwarf.o new file mode 100644 index 0000000..5164271 Binary files /dev/null and b/vasm-1/obj/m68k_mot_dwarf.o differ diff --git a/vasm-1/obj/m68k_mot_error.o b/vasm-1/obj/m68k_mot_error.o new file mode 100644 index 0000000..755708e Binary files /dev/null and b/vasm-1/obj/m68k_mot_error.o differ diff --git a/vasm-1/obj/m68k_mot_expr.o b/vasm-1/obj/m68k_mot_expr.o new file mode 100644 index 0000000..5e9a63a Binary files /dev/null and b/vasm-1/obj/m68k_mot_expr.o differ diff --git a/vasm-1/obj/m68k_mot_hugeint.o b/vasm-1/obj/m68k_mot_hugeint.o new file mode 100644 index 0000000..2728077 Binary files /dev/null and b/vasm-1/obj/m68k_mot_hugeint.o differ diff --git a/vasm-1/obj/m68k_mot_osdep.o b/vasm-1/obj/m68k_mot_osdep.o new file mode 100644 index 0000000..4cd60c8 Binary files /dev/null and b/vasm-1/obj/m68k_mot_osdep.o differ diff --git a/vasm-1/obj/m68k_mot_output_aout.o b/vasm-1/obj/m68k_mot_output_aout.o new file mode 100644 index 0000000..ced516a Binary files /dev/null and b/vasm-1/obj/m68k_mot_output_aout.o differ diff --git a/vasm-1/obj/m68k_mot_output_bin.o b/vasm-1/obj/m68k_mot_output_bin.o new file mode 100644 index 0000000..a029fcd Binary files /dev/null and b/vasm-1/obj/m68k_mot_output_bin.o differ diff --git a/vasm-1/obj/m68k_mot_output_elf.o b/vasm-1/obj/m68k_mot_output_elf.o new file mode 100644 index 0000000..d0e9b44 Binary files /dev/null and b/vasm-1/obj/m68k_mot_output_elf.o differ diff --git a/vasm-1/obj/m68k_mot_output_hunk.o b/vasm-1/obj/m68k_mot_output_hunk.o new file mode 100644 index 0000000..d6de9bc Binary files /dev/null and b/vasm-1/obj/m68k_mot_output_hunk.o differ diff --git a/vasm-1/obj/m68k_mot_output_srec.o b/vasm-1/obj/m68k_mot_output_srec.o new file mode 100644 index 0000000..8bc5574 Binary files /dev/null and b/vasm-1/obj/m68k_mot_output_srec.o differ diff --git a/vasm-1/obj/m68k_mot_output_test.o b/vasm-1/obj/m68k_mot_output_test.o new file mode 100644 index 0000000..0743a34 Binary files /dev/null and b/vasm-1/obj/m68k_mot_output_test.o differ diff --git a/vasm-1/obj/m68k_mot_output_tos.o b/vasm-1/obj/m68k_mot_output_tos.o new file mode 100644 index 0000000..130af0d Binary files /dev/null and b/vasm-1/obj/m68k_mot_output_tos.o differ diff --git a/vasm-1/obj/m68k_mot_output_vobj.o b/vasm-1/obj/m68k_mot_output_vobj.o new file mode 100644 index 0000000..cd5535d Binary files /dev/null and b/vasm-1/obj/m68k_mot_output_vobj.o differ diff --git a/vasm-1/obj/m68k_mot_output_xfile.o b/vasm-1/obj/m68k_mot_output_xfile.o new file mode 100644 index 0000000..bc559c4 Binary files /dev/null and b/vasm-1/obj/m68k_mot_output_xfile.o differ diff --git a/vasm-1/obj/m68k_mot_parse.o b/vasm-1/obj/m68k_mot_parse.o new file mode 100644 index 0000000..3267bb6 Binary files /dev/null and b/vasm-1/obj/m68k_mot_parse.o differ diff --git a/vasm-1/obj/m68k_mot_reloc.o b/vasm-1/obj/m68k_mot_reloc.o new file mode 100644 index 0000000..33b3c0a Binary files /dev/null and b/vasm-1/obj/m68k_mot_reloc.o differ diff --git a/vasm-1/obj/m68k_mot_supp.o b/vasm-1/obj/m68k_mot_supp.o new file mode 100644 index 0000000..3b880ad Binary files /dev/null and b/vasm-1/obj/m68k_mot_supp.o differ diff --git a/vasm-1/obj/m68k_mot_symbol.o b/vasm-1/obj/m68k_mot_symbol.o new file mode 100644 index 0000000..eb755a8 Binary files /dev/null and b/vasm-1/obj/m68k_mot_symbol.o differ diff --git a/vasm-1/obj/m68k_mot_symtab.o b/vasm-1/obj/m68k_mot_symtab.o new file mode 100644 index 0000000..2d7470e Binary files /dev/null and b/vasm-1/obj/m68k_mot_symtab.o differ diff --git a/vasm-1/obj/m68k_mot_syntax.o b/vasm-1/obj/m68k_mot_syntax.o new file mode 100644 index 0000000..e6a8433 Binary files /dev/null and b/vasm-1/obj/m68k_mot_syntax.o differ diff --git a/vasm-1/obj/m68k_mot_vasm.o b/vasm-1/obj/m68k_mot_vasm.o new file mode 100644 index 0000000..980dbf0 Binary files /dev/null and b/vasm-1/obj/m68k_mot_vasm.o differ diff --git a/vasm-1/vasmm68k_mot b/vasm-1/vasmm68k_mot new file mode 100755 index 0000000..617d85c Binary files /dev/null and b/vasm-1/vasmm68k_mot differ diff --git a/xo-rom-enable-netboot.py b/xo-rom-enable-netboot.py index f1839e3..5f8faa2 100755 --- a/xo-rom-enable-netboot.py +++ b/xo-rom-enable-netboot.py @@ -34,7 +34,7 @@ with open(sys.argv[1], 'r+b') as f: garbage_location = 0x67046 # The MacsBug copyright string in the ROM Disk # Make out own structure, as adapted from NetBoot.h - the_netboot_structure = struct.pack('>BBBB BB 8s 32s 8s H', + the_netboot_structure = struct.pack('>BBBB BB 16s 32s 8s H', # Note that "int"s are 4 bytes, somehow! # First 4 bytes at PRAM+4 1, # char osType; /* preferred os to boot from */ 1, # char protocol; /* preferred protocol to boot from */ @@ -44,12 +44,16 @@ with open(sys.argv[1], 'r+b') as f: # Now, the AppleTalk-protocol-specific part 0, # unsigned char nbpVars; /* address of last server that we booted off of */ 0, # unsigned char timeout; /* seconds to wait for bootserver response */ - b'', # unsigned int signature[4]; /* image signature */ + b'', # unsigned int signature[4]; /* image signature */ Elliot notes: zeroes match anything! b'Elliot', # char userName[31]; /* an array of char, no length byte */ b'volapuk', # char password[8]; /* '' */ - 0x7777, # short serverNum; /* the server number */ + 0xBABE, # short serverNum; /* the server number */ ).ljust(72, b'\0') + # the_netboot_structure = bytearray(the_netboot_structure) + # for i, j in enumerate(range(54, len(the_netboot_structure))): + # the_netboot_structure[j] = i + # This is the guts of the NetBoot ReadPRAM procedure f.seek(0x1DF08) write_asm(f, f''' @@ -64,6 +68,17 @@ with open(sys.argv[1], 'r+b') as f: f.seek(garbage_location) f.write(the_netboot_structure) + # Do the dodgy... cancel signature validation! + f.seek(0x21A84) + while f.tell() < 0x21A98: + f.write(b'Nq') # nop + + # Work around Mini vMac's cutesy many-drives hack (it steals out preferred drivenum of 4 from us) + f.seek(0x1DF51) # AddMyDrive: moveq #4,d9 + f.write(b'\x10') + f.seek(0x1DFDF) # myExtFSFilter: cmp.w #4,d0 + f.write(b'\x10') + # Enable this to make a SysError, for rudimentaly debug output - # f.seek(0x1DD4E) - # f.write(b'\xA9\xC9') + f.seek(0x878C) + f.write(assemble('move.w #0xFFFF,D0 \n .2byte 0xA9C9'))