68kMLA Classic Interface
This is a version of the 68kMLA forums for viewing on your favorite old mac. Visitors on modern platforms may prefer the main site.
| Click here to select a new forum. | | Skipping the Startup Memory Test | Posted by: joevt on 2025-08-28 16:38:55 0x1258 is Link2 which is probably going to be a Power PC ROM address (looks like 0xfff##### - last 1 MB of 4 MB ROM). It appears to only be used for calling SerialTestManager tests?
Can you post one of your NVRAM dumps so I can compare?
Is your ROM 077d.28f1 checksum 96cd923d or 077d.28f2 checksum 9630c68b?
I don't think that matters since they have the same ExceptionTable, HWInit (except for one byte at the end?), and OpenFW parts. | Posted by: jmacz on 2025-08-28 17:07:02 Attached two outputs from your tool, one after booting without ram test and one after booting with ram test.
ROM version 077d.28f2 checksum $9630c68b | Posted by: jmacz on 2025-08-28 18:47:46 My guess is it's the same everywhere and the bit I saw toggling was just a coincidence because that byte (and the 3 bytes before it) certainly looks like an address.
From the source you shared, it's a 32bit read/write of offset 0x1040 and a zero skips the test and a non-zero runs it.
That does suggest in System 7, it does write a non-zero value at some point after boot (probably shutdown as well).
If I want to put a zero there to skip the test, I need to ensure I overwrite it after the System touches it or patch the System call to not write the non-zero value. | Posted by: joevt on 2025-08-28 20:32:14
Attached two outputs from your tool, one after booting without ram test and one after booting with ram test. 0x1258 is zero in both.
I see 0x1254 = Link1 change from fff201f8 in FastConfigDump to fff20270 in SlowConfigDump.
fff20000 (3MB + 128K, size 64K) is the address of HWInit in the ROM, according to the results created by the tbxi command.
https://github.com/elliotnunn/tbxi
fff201f8 is the return address for the call at 0x1f4 in HWInit (in .POST) to CheckForInitialzation.
fff20270 is the return address for the call at 0x26c in HWInit (in ColdBoot) to RunTests.
That seems like a sufficient indication that the tests were run - as long as nothing else uses Link1. Searching HWInit.txt shows no other occurrences of Link1.
I used the MPW DumpXCOFF command using
https://github.com/ksherlock/mpw
to disassemble HWInit but it seems to be an incomplete dump. Maybe running the command in real MPW would produce a complete dump?
But at least the disassembly includes the parts I'm talking about. The parts match what's in the Diagnostics.s assembly file (though I didn't check every instruction or try to compile Diagnostics.s). | Posted by: jmacz on 2025-08-28 21:05:51 I'm sorry, I think my brain is fried... Here are the two lines from the fast dump and the slow dump:
27F448FE FFF0D000 5D5CC8CE FFF0D000 FFF04C4C FFF201F8 00000000 00000000 // FAST
27F45CFE FFF0D000 DF7DC8CE FFF0D000 FFF04C4C FFF20270 00000000 00000000 // SLOW
^
The bit that was flipping is indicated above. Contrary to what I wrote, it's actually offset 0x1256. My post #10 in this thread should have said 0x1256 instead of 0x1258 and then I repeated 0x1258 in subsequent posts. And that's why I thought it was within your range but then confused myself with that typo of 0x1258 again. Sorry about that. So I think 0x1256 was within the range you saw reads/writes to but it was not the change I was looking for. | Posted by: joevt on 2025-08-28 21:32:23
The bit that was flipping is indicated above. Contrary to what I wrote, it's actually offset 0x1256. My post #10 in this thread should have said 0x1256 instead of 0x1258 and then I repeated 0x1258 in subsequent posts. And that's why I thought it was within your range but then confused myself with that typo of 0x1258 again. Sorry about that. So I think 0x1256 was within the range you saw reads/writes to but not the change I was looking for. Right. 0x1256 which is part of the 32 bit value at 0x1254. 0x1254 is Link1 and it is not 32 different bits - it is a 32 bit value which is a return address to code in ROM (specifically in the HWInit part of the ROM). There's no RAM or stack during this time in the boot process, so offsets 0x1000..0x12ff in NVRAM are used. Return addresses are sometimes stored in the NVRAM Link# fields in that range. | Posted by: jmacz on 2025-08-30 17:05:26 I traced through parts of the shutdown code via MacsBug today under MacOS 8.6 and found where it's writing that '9' to NVRAM. There's a chain of handlers invoked during the shutdown and it looks to be in one of them -- I'm guessing these are the registered shutdown handlers. The first handler unmounts the drives and ejects any floppy disks. The second handler is the one I'm interested in. It calls gestalt a few times, grabs the trap address for the Expansion Manager and then looks like it conditionally writes a '0x09' to a byte in NVRAM. Need to look for something similar in System 7.6.1 and see if there it's writing it unconditionally. | Posted by: jmacz on 2025-08-30 18:11:34 The gestalt calls seem to be for the 'misc' and 'kdia' selectors. If 'misc' is supported, it's clearing something out a $0ddc and if 'kdia' is supported, it's reading something at $0dd8 offset $68. If that value is non-zero it is written to NVRAM otherwise it defaults to $09. It then reads bit 6 of $2400 and if set, skips the write. Then it checks bit 1 at $2400, bit 4 at $2401, and bit 3 at $2402 and if any of those are set, it writes to NVRAM at the byte at offset $1043 and then triggers the $032f selector with the expansion manager. I don't think I see any other checks in the handler for whether it should write to NVRAM (0x09 or whatever was at $0dd8) so the preference from the Memory control panel is at at one of those bits in $2400-$2402? | Posted by: jmacz on 2025-08-30 18:20:09 Oh hmm.. I turned off the memory tests and stepped through the code again (this is still on MacOS 8.6). I wanted to see where it branches away from writing to NVRAM. With the memory tests turned off, it looks like the call to Gestalt for the 'kdia' selector returns 0. And it bails there. | Posted by: joevt on 2025-08-30 23:32:25
The gestalt calls seem to be for the 'misc' and 'kdia' selectors. These appear to be from the gpch resources.
A couple bits of misc are documented in Inside Macintosh. What bit does it check?
kdia is undocumented.
If 'misc' is supported, it's clearing something out a $0ddc and if 'kdia' is supported, it's reading something at $0dd8 offset $68. If that value is non-zero it is written to NVRAM otherwise it defaults to $09. $ddc is BootGlobPtr which I think points to a StartGlobals record.
$dd8 is UnivInfoPtr which is type ProductInfo. $68 is beyond the offsets documented in supermario (unless you meant decimal 68). The version is a byte at offset $17. supermario defines version 0 and version 1; both seem to have the same set of fields.
It then reads bit 6 of $2400 and if set, skips the write. Then it checks bit 1 at $2400, bit 4 at $2401, and bit 3 at $2402 and if any of those are set, it writes to NVRAM at the byte at offset $1043 and then triggers the $032f selector with the expansion manager. I don't think I see any other checks in the handler for whether it should write to NVRAM (0x09 or whatever was at $0dd8) so the preference from the Memory control panel is at at one of those bits in $2400-$2402? Where does the $2400 address come from? Is it a field of BootGlobPtr or UnivInfoPtr or is it from a different low memory global (system symbol)?
Selector 032f is undocumented. 303C 032F AAF3 is found in gpch resources. My DumpNameRegistry source code has these:
kReadNVRAMSelector = $022E;
kWriteNVRAMSelector = $032F; which I mentioned at https://68kmla.org/bb/index.php?threads/the-great-gazelle-pci-hack-thread-part-2.38360/post-503281
In terms of CFM, maybe these get to NVRAMRead and NVRAMWrite in NVRAMServicesLib? I haven't checked. | Posted by: jmacz on 2025-08-31 07:54:16
A couple bits of misc are documented in Inside Macintosh. What bit does it check?
Bit 1 is tested. I think I saw that Bit 0 and Bit 2 are documented only.
$ddc is BootGlobPtr which I think points to a StartGlobals record.
$dd8 is UnivInfoPtr which is type ProductInfo. $68 is beyond the offsets documented in supermario (unless you meant decimal 68). The version is a byte at offset $17. supermario defines version 0 and version 1; both seem to have the same set of fields.
Hex $68.
Where does the $2400 address come from? Is it a field of BootGlobPtr or UnivInfoPtr or is it from a different low memory global (system symbol)?
This was a static address so another global. | Posted by: jmacz on 2025-08-31 11:10:03 Traced through on System 7.6.1 and it's very similar.
- Same check of bit 1 on the response to the 'misc' gestalt selector before deciding whether to clear a field at $0ddc.
- Same check to determine if the expansion manager trap exists.
- On System 7.6.1, it does NOT look for the 'kdia' gestalt selector but just goes to look at $0dd8 and attempts to read offset $68 and if it's non-zero, uses it otherwise uses 0x09.
- It then checks bit 6 at $2400 and if it's set, skips the NVRAM update.
- It then checks bit 1 at $2400, 4 at $2401, 3 at $2402, and if any are set, it writes to NVRAM, otherwise skips.
- Uses the same NVRAM write selector (0x32f) to update NVRAM.
Just need to understand what is at $2400-$2402 and how it's set. Will need to look at the Memory control panel code now on OS 8.6. | Posted by: jmacz on 2025-08-31 13:54:42 Looked at the disassembled code for the Memory control panel in Mac OS 8.6. So far look at what happens when you close the control panel. It looks like it saves a copy of the settings inside the System Folder -> Preferences -> Memory Preferences file. If the ram test is disabled, it creates a resource of type 'kdia' with ID=0 in that preferences file. It is 0 length so no contents. If the ram test is enabled, it removes this resource if it exists. It looks like it's just a copy of the settings to keep for itself. I don't really see anything else interesting when it closes.
Will look at if there's anything when the two radio buttons are toggled to see if it does something live when the user clicks on them. | Posted by: jmacz on 2025-08-31 18:45:46 For the MacOS 8.6 Memory CDEV, what it does:
- On mouse click of the Startup Memory Tests On
- Calls _DeleteGestaltValue for 'kdia'.
- On mouse click of the Startup Memory Tests Off
- Calls _NewGestaltValue for 'kdia'.
- On close of the control panel
- Makes changes to the System Folder -> Preferences -> Memory Preferences file
- If Startup Memory Tests On, removes any 'kdia' resource from the preferences file.
- If Startup Memory Tests Off, creates a 'kdia' resource ID=0 with 0 contents in the preferences file.
Then on shutdown:
- Calls gestalt for 'kdia'
- If noErr, skip writing anything to NVRAM.
- If err:
- Checks bit 6 at $2400 and if it's set, skips writing anything to NVRAM.
- Checks bit 1 at $2400, 4 at $2401, 3 at $2402, and if any are set, it writes 0x09 or value from offset $68 at $0dd8 to NVRAM, otherwise skips.
On MacOS 8.6, the main gate seems to be that 'kdia' gestalt.
On System 7.6.1, the 'kdia' checks are missing.. but it still has the checks for the memory at $2400-$2402. Seems like the $2400-$2402 is a hardware check of some kind and probably not pertinent (to see if NVRAM is available or ?). In that sense it looks like on System 7.6.1, it will always force a memory check.
Going to look at the shutdown handlers (never written one before) and see if registering one that runs last could overwrite the change to NVRAM. Or if that won't work, will have to look into a patch, either dynamic at runtime or static. | Posted by: jmacz on 2025-08-31 21:08:59 Looks like I should be able to register a shutdown procedure that runs after Apple's that writes to NVRAM. Already see my procedure being called after Apple's. Only question is whether it's too late in the shutdown sequence and some subsystems aren't available anymore. But we'll see. | Posted by: jmacz on 2025-08-31 22:19:11 Ok, cooked up a system extension that will register a shutdown proc and overwrite that 0x09 with a 0x00 which then skips the ram test on the next cold boot.
All it does is register a shutdown procedure which executes before power off and essentially mimics what Apple does (even in System 7.6.1) but instead of writing the 0x09, it writes a 0x00 instead. It also does the check for the presence of the expansion manager trap as well as the checks against address $2400-$2402 as I believe it might be hardware checks on whether this is allowed or not. I skipped the gestalt calls ('misc' and 'kdia') as whatever Apple's code does with the 'misc' response is already done as I'm not removing their code. And the 'kdia' check is not present in Apple's 7.6.1 implementation so I skipped that as well.
Tested on System 7.6.1 only and on my Power Macintosh 8500. Seems to work ok. Attached below if anyone wants to try it.

May work on a CDEV version later that provides the ability to toggle it on/off. But I don't think it's a big deal to just disable it using Extension Manager if you want the ram test on next cold boot. | Posted by: joevt on 2025-08-31 23:23:19 If you grep for (\$|0x)0*2400\b you find it in
Boot3.a, UniversalEqu.h, InternalOnlyEqu.a, InternalOnlyEqu.r, StartInit.a, ShutDownMgr.a
elliotnunn/boot3
elliotnunn/CubeE
elliotnunn/mac-rom
elliotnunn/supermario
0xDD0 is AddrMapFlags - a set of 32 boolean flags (one per bit).
0x2400 is AdrMapFlags1 - 32 additional boolean flags.
0x2404 is AdrMapFlags2 - last 32 boolean flags. 96 total.
TestForBaseAddr describes the usage of the flags.
A flag bit (one of BasesValidFlags) set to 1 means there's a base address corresponding to that bit in the DecoderInfo struct pointed to by the decoderInfoPtr field (not a pointer - it's an offset) of the ProductInfo struct pointed to by the low memory global UnivInfoPtr at 0xDD8.
GetUnivInfoBaseAddr describes the usage of decoderInfoPtr.
These are a list of the base addresses and their offset in DecoderInfo struct (divide by 4 for the corresponding BasesValidFlags bit number in AddrMapFlags):
0x000 ROMAddr // corresponding BasesValidFlags name is ROMExists
0x004 DiagROMAddr
0x008 VIA1Addr
0x00c SCCRdAddr
0x010 SCCWrAddr
0x014 IWMAddr
0x018 PWMAddr
0x01c SoundAddr
0x020 SCSIAddr
0x024 SCSIDackAddr
0x028 SCSIHskAddr
0x02c VIA2Addr
0x030 ASCAddr
0x034 RBVAddr
0x038 VDACAddr
0x03c SCSIDMAAddr
0x040 SWIMIOPAddr
0x044 SCCIOPAddr
0x048 OSSAddr
0x04c FMCAddr
0x050 RPUAddr
0x054 OrwellAddr
0x058 JAWSAddr
0x05c SonicAddr
0x060 SCSI96Addr1
0x064 SCSI96Addr2
0x068 DAFBAddr
0x06c PSCAddr
0x070 ROMPhysAddr
0x074 PatchROMAddr
0x078 NewAgeAddr
0x07c Unused31Addr
0x080 SingerAddr
0x084 DSPAddr
0x088 MACEAddr
0x08c MUNIAddr
0x090 AMICAddr
0x094 PrattAddr
0x098 SWIM3Addr
0x09c AwacsAddr
0x0a0 CivicAddr
0x0a4 SebastianAddr
0x0a8 BARTAddr
0x0ac GrandCentralAddr
0x0b0 Unused44Addr
0x0b4 Unused45Addr
0x0b8 Unused46Addr
0x0bc Unused47Addr
0x0c0 Unused48Addr
0x0c4 Unused49Addr
0x0c8 Unused50Addr
0x0cc Unused51Addr
0x0d0 Unused52Addr
0x0d4 Unused53Addr
0x0d8 Unused54Addr
0x0dc Unused55Addr
0x0e0 Unused56Addr
0x0e4 Unused57Addr
0x0e8 Unused58Addr
0x0ec Unused59Addr
0x0f0 Unused60Addr
0x0f4 Unused61Addr
0x0f8 FooAddr
0x0fc Unused63Addr
0x100 Unused64Addr
0x104 BarAddr
0x108 Unused66Addr
0x10c Unused67Addr
0x110 Unused68Addr
0x114 Unused69Addr
0x118 Unused70Addr
0x11c Unused71Addr
0x120 Unused72Addr
0x124 Unused73Addr
0x128 Unused74Addr
0x12c Unused75Addr
0x130 Unused76Addr
0x134 Unused77Addr
0x138 Unused78Addr
0x13c Unused79Addr
0x140 Unused80Addr
0x144 Unused81Addr
0x148 Unused82Addr
0x14c Unused83Addr
0x150 Unused84Addr
0x154 Unused85Addr
0x158 Unused86Addr
0x15c Unused87Addr
0x160 Unused88Addr
0x164 Unused89Addr
0x168 Unused90Addr
0x16c Unused91Addr
0x170 Unused92Addr
0x174 Unused93Addr
0x178 Unused94Addr
0x17c Unused95Addr | Posted by: joevt on 2025-08-31 23:46:23
The gestalt calls seem to be for the 'misc' and 'kdia' selectors. If 'misc' is supported, it's clearing something out a $0ddc and if 'kdia' is supported, it's reading something at $0dd8 offset $68. If that value is non-zero it is written to NVRAM otherwise it defaults to $09. It then reads bit 6 of $2400 and if set, skips the write. Then it checks bit 1 at $2400, bit 4 at $2401, and bit 3 at $2402 and if any of those are set, it writes to NVRAM at the byte at offset $1043 and then triggers the $032f selector with the expansion manager. I don't think I see any other checks in the handler for whether it should write to NVRAM (0x09 or whatever was at $0dd8) so the preference from the Memory control panel is at at one of those bits in $2400-$2402?
Traced through on System 7.6.1 and it's very similar.
- Same check of bit 1 on the response to the 'misc' gestalt selector before deciding whether to clear a field at $0ddc.
- Same check to determine if the expansion manager trap exists.
- On System 7.6.1, it does NOT look for the 'kdia' gestalt selector but just goes to look at $0dd8 and attempts to read offset $68 and if it's non-zero, uses it otherwise uses 0x09.
- It then checks bit 6 at $2400 and if it's set, skips the NVRAM update.
- It then checks bit 1 at $2400, 4 at $2401, 3 at $2402, and if any are set, it writes to NVRAM, otherwise skips.
- Uses the same NVRAM write selector (0x32f) to update NVRAM.
Just need to understand what is at $2400-$2402 and how it's set. Will need to look at the Memory control panel code now on OS 8.6.
Then on shutdown:
- Calls gestalt for 'kdia'
- If noErr, skip writing anything to NVRAM.
- If err:
- Checks bit 6 at $2400 and if it's set, skips writing anything to NVRAM.
- Checks bit 1 at $2400, 4 at $2401, 3 at $2402, and if any are set, it writes 0x09 or value from offset $68 at $0dd8 to NVRAM, otherwise skips.
On MacOS 8.6, the main gate seems to be that 'kdia' gestalt.
On System 7.6.1, the 'kdia' checks are missing.. but it still has the checks for the memory at $2400-$2402. Seems like the $2400-$2402 is a hardware check of some kind and probably not pertinent (to see if NVRAM is available or ?). In that sense it looks like on System 7.6.1, it will always force a memory check.
43 0x0ac GrandCentralAddr GrandCentralExists,
44 0x0b0 Unused44Addr PBX1Exists,
45 0x0b4 Unused45Addr PBX2Exists,
46 0x0b8 Unused46Addr PBX3Exists,
47 0x0bc Unused47Addr ATAExists,
48 0x0c0 Unused48Addr HammerHeadExists,
49 0x0c4 Unused49Addr PlatinumExists,
50 0x0c8 Unused50Addr Pratt2Exists,
51 0x0cc Unused51Addr PSXExists,
52 0x0d0 Unused52Addr OHareExists,
53 0x0d4 Unused53Addr GrackleExists,
54 0x0d8 Unused54Addr HydraExists,
55 0x0dc Unused55Addr SuperIOExists,
56 0x0e0 Unused56Addr SIOExists,
57 0x0e4 Unused57Addr HeathrowExists,
58 0x0e8 Unused58Addr MFMFloppyExists,
59 0x0ec Unused59Addr MFMMethodsVectorExists,
60 0x0f0 Unused60Addr FatManExists,
61 0x0f4 Unused61Addr OpenPICExists,
62 0x0f8 FooAddr CHRPNess,
63 0x0fc Unused63Addr GatwickExists
bit 6 of 2400 = 32 + 24 + 6 = 62 = CHRPNess
bit 1 of 2400 = 32 + 24 + 1 = 57 = HeathrowExists
bit 4 of 2401 = 32 + 16 + 4 = 52 = OHareExists
bit 3 of 2402 = 32 + 8 + 3 = 43 = GrandCentralAddr
NVRAM is part of GrandCentral, OHare, or Heathrow. These are all CHRP machines.
I suppose it may be possible to scan ROM dumps to find ROMs that set these bits. | Posted by: joevt on 2025-09-01 00:23:43 UniversalTables.a shows how the bits are setup for different machines. Just need an algorithm to find this in the ROM.
Edited my previous post above. | Posted by: jmacz on 2025-09-01 07:49:35 The code seems to do the "run startup ram test" byte write as long as CHRPNess (bit 6 of $2400) is set AND one of the other three (HeathrowExists, OHareExists, GrandCentralAddr) is set.
I have done the same tests/checks in the No Ram Test system extension so I think any model that Apple supported with their code should work here.
The read of the 'misc' gestalt is unnecessary as Apple's code seems to do that no matter what before doing anything else with 'kdia' or the memory at $2400-$2402, so since that code runs before mine, I don't have to mimic it.
EDIT: The only thing I should probably go back and add is reading offset $68 of $0dd8, and using that instead of 0x09 if it's non zero. Not clear to me whether some of the other ROMs will want a different value there and if that's what the check is for or not.
Actually the $0dd8 stuff doesn't matter either because it would be important to know if you are enabling the startup ram tests but I'm putting a zero there to not run them so doesn't matter. The only concern is if some other models are using a non-zero value to signify not to run the test but I wouldn't think that would be the case. | | < 2 > |
|