Imaging a Bootable Mac OS 9 CD the Hard Way

Branchus

Administrator
Staff member
Founder
Sep 2, 2021
241
523
93
(The following is a reproduction of this article.)

I was recently contacted by a friend who was trying to get an old PowerMac 7300 up and running. They were looking for a disk image they could use to burn a bootable Mac OS 9.1 installer CD. Take note of that word: “bootable”, because that’s the really important part. These old computers can’t just boot into Internet Recovery or a USB stick. For computers of this vintage you need physical CD media to boot and install from.

My immediate response was to send him to the Mac OS9 page of the Macintosh Garden to download an image of the installer. Sure, “the Garden” is slow, and the search engine is clunky as hell (sorry fogWraith!) but it’s easily the most complete archive of vintage Mac abandonware out there.

Spare a thought for the Windows users​

The reply I received from my friend was clearly from a very frustrated individual:
“…I used that web site and wasted all afternoon (Extremely SLOW Download Speed) on a 396MB zip (supposed to be ‘Mac OS 9.0 International version’), which I thought was an .iso, but was a .toast file. What can I do with a Toast file in Windows?”

And that got me thinking: what about all of these poor Windows users who want to dabble in vintage Mac technology? All of the archived files are very Mac-centric. Well as it turns out, there is a really simple solution, but where’s the fun in that? Let's go through all of the complicated stuff first.

Always wanting to help out a fellow vintage Mac enthusiast, I told him I would create an .iso disk image that he could use on his Windows machine to burn a bootable Mac OS 9.1 CD. I had the original disk, so I could ensure everything was done right, giving him the best chance of success.

I decided I would do everything on a PowerPC Mac. I have a 2.5GHz quad core G5 tower under my desk that I can fire up any time I need to work with an older OS. My plan was to boot into OSX Leopard, insert the original CD, image it and then send it off to my friend to use with the 7300.

My first (wrong) assumption about Disk Utility​

At first I tried Disk Utility, Apple’s own drive formatting software. I inserted the original disc, selected it in Disk Utility and chose “New Image.” I selected “DVD/CD Master,” which produced a .cdr file, Apple’s preferred extension for a raw optical disc image. To (hopefully) make the file more compatible with Windows burning software, I used the command-line utility hdiutil to convert it into a plain .iso file.

I burned a copy to a blank CD, grabbed my trusty Wallstreet G3 PowerBook and attempted to boot to the CD by holding the “c” key on startup.

No luck. It booted straight into the OS on the internal hard drive and completely ignored the CD. The CD still mounted and all the data was there, it just wasn’t bootable. So what next? If the Mac’s own Disk Utility can‘t make a bootable CD, what will?

My second assumption: dd to the rescue​

For my next attempt I would try the command line utility dd, which should allow me to do a raw sector-by-sector copy of the disk and make an exact replica of the original. I burned the disk image created by dd to a blank CD and once again, all the data was there, but I couldn’t boot from it. But then it occurred to me that dd uses a default byte size of 512 and CD-ROM data sectors are 2048 bytes, not 512. So specifying a 2048 byte size would surely be the key to success?

No, it wasn’t. Still not bootable.

Invisible interference​

At this point I looked into some alternatives, specifically readcd, a command-line utility designed to read optical media at a lower level and create disc images directly from the drive. I installed readcd on my G5 as part of the Schilytools repository. After a few technical challenges I finally got it running, and my hope was that direct communication with the optical drive would give me a true, raw image of the original disc; including the Apple Partition Map and boot driver partitions.

On my first attempt, I was greeted with the following error:
Warning, ‘diskarbitrationd’ is running and does not allow us to send SCSI commands to the drive.

This was the turning point; the realisation that explained why every previous attempt had failed.

Disk Arbitration is a background service in macOS responsible for detecting removable media and publishing it to the BSD disk layer. When a disc is inserted, it creates device nodes such as /dev/disk2 and allows the volume to be mounted and accessed in Finder. However, in doing so, it also mediates access to the drive. Tools that rely on the BSD block layer (including dd) are therefore limited to what the operating system chooses to expose.

readcd, on the other hand, communicates directly with the optical drive using SCSI/MMC commands. For that to work, it needs exclusive access. With Disk Arbitration running, that exclusive access is denied.

So perhaps the solution was simple: disable Disk Arbitration and then use dd to create the image? It sounds plausible, but without Disk Arbitration running, the disc never gets published to the BSD device list. No /dev/disk2. And without those device nodes, dd has nothing to read from.

A perfect Catch-22.

The real solution​

Thankfully readcd could still give me what I wanted, so I disabled Disk Arbitration, used readcd to extract a raw ISO from the CD – including the boot partition – and then re-enabled Disk Arbitration to restore the system back to its original state. And with the help of ChatGPT, I also created a shell script to automate this process for any time I wanted to image one of my vintage bootable CDs.

It worked. While dd only captured the data from the one main partition of the CD, readcd captured nine separate partitions, and I had now devised a repeatable process for any time I want to archive any of my original, bootable optical media into a raw .iso file.

At this point I could spend the next few paragraphs providing intricate details of exactly how to replicate this process, but that’s where it all gets a bit silly. Remember at the start I said there was a really simple solution? After a very brief moment of satisfaction from my accomplishment, I came to the realisation that it had all been for nothing. As it turns out, all that is required to get a Toast disk image to work with Windows disk burning software like ImgBurn is to rename the file with an .iso file extension instead of .toast. Same goes with use with BlueSCSI and ZuluSCSI, just make sure you use the correct CD naming convention: “CDx0_2048.iso” where you replace “x” with your preferred SCSI ID and you’re good to go.

Oh well, it was a fun discovery process.
 
  • Like
Reactions: phunguss

joevt

Tinkerer
Mar 5, 2023
235
96
28
A CD has multiple "slices":

Code:
diskutil list /dev/disk18
/dev/disk18 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:        CD_partition_scheme                        *755.4 MB   disk18
   1:     Apple_partition_scheme ⁨⁩                        657.8 MB   disk18s1
   2:        Apple_partition_map ⁨⁩                        32.3 KB    disk18s1s1
   3:             Apple_Driver43 ⁨⁩                        28.7 KB    disk18s1s2
   4:          Apple_Driver43_CD ⁨⁩                        61.4 KB    disk18s1s3
   5:         Apple_Driver_ATAPI ⁨⁩                        28.7 KB    disk18s1s5
   6:         Apple_Driver_ATAPI ⁨⁩                        61.4 KB    disk18s1s6
   7:              Apple_Patches ⁨⁩                        262.1 KB   disk18s1s7
   8:                  Apple_HFS ⁨Mac OS X Install CD⁩     656.7 MB   disk18s1s9
You probably used dd with the slice of a partition /dev/disk18s1s9.

You probably should have used dd with the slice of the entire disk /dev/disk18s1. This typically has 2048 byte blocks.

If you dd the CD_partition_scheme /dev/disk18, then you get extra CD data (2352 bytes per block) which has some bytes before each 2048 byte block and lots of bytes after each 2048 byte block. These bytes are usually unnecessary.
657.8 MB * 2352 / 2048 = 755.4 MB.

Older versions of macOS may show different names for the CD slices.

DingusPPC emulator will handle CD images with 2352 sized blocks or 2048 sized blocks. My fork (and the InfiniteMac version) accepts hard disk images (all partitions) or single partition images and can concatenate them together virtually and add the Mac OS 9 drivers to make sure the single partition is bootable.

Code:
 * Sector Areas, Sector Types
 *
 * Bytes Per Type      CDDA       Mode1      Mode2   Mode2Form1 Mode2Form2
 *       Per Area  +----------+----------+----------+----------+----------+
 * Sync            | 0        | 12       | 12       | 12       | 12       |
 * Header          | 0        | 4        | 4        | 4        | 4        |
 * SubHeader       | 0        | 0        | 0        | 8        | 8        |
 * User            | 2352     | 2048     | 2336     | 2048     | 2328     |
 * Auxiliary       | 0        | 288      | 0        | 280      | 0        |
 * ErrorFlags      | 294      | 294      | 294      | 294      | 294      |
 * SubChannel      | 96       | 96       | 96       | 96       | 96       |
 *                 +----------+----------+----------+----------+----------+
A data CD is usually Mode1 or Mode2Form1. The User area contains the data (2048 bytes). ErrorFlags and SubChannel are data from the controller, not the CD.

Older operating systems might name the slices differently.
I guess if the OS doesn't know the file system then it will have name CD_ROM_Mode_2_Form_1 or CD_ROM_Mode_1 instead of Apple_partition_scheme.
Other possibilities: CD_DA, CD_ROM_Mode_2, CD_ROM_Mode_2_Form_2 (but not for Apple_partition_scheme).
 

Branchus

Administrator
Staff member
Founder
Sep 2, 2021
241
523
93
You probably used dd with the slice of a partition /dev/disk18s1s9.
I can tell you exactly what I did:
Code:
dd if=/dev/disk2

And that resulted in an image that did not retain any of the partitions.

I have since tried your suggestion of:
Code:
if=/dev/disk2s1

And it worked at treat. All partitions retained. Thanks for the tip!
 
  • Like
Reactions: ClassicHasClass