From c06ed07eab85f24448282ff8296dc55d9c538801 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Sun, 16 Feb 2025 16:19:28 -0800 Subject: [PATCH] Add Macintosh boot block image This adds a 1024-byte blob with a Macintosh boot image for use with HFS volumes. The code that applies it during disk formatting is currently disabled while we figure out how best to apply it. Information about the boot block has been added to the HFS doc. (issue #42) --- DiskArc/FS/HFS-notes.md | 55 ++++++++++++++++++++++++++ DiskArc/FS/HFS.cs | 85 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 137 insertions(+), 3 deletions(-) diff --git a/DiskArc/FS/HFS-notes.md b/DiskArc/FS/HFS-notes.md index ab251df..914a90d 100644 --- a/DiskArc/FS/HFS-notes.md +++ b/DiskArc/FS/HFS-notes.md @@ -498,6 +498,61 @@ FXInfo / FndrOpaqueInfo (16 bytes) +$0c / 4: fdPutAway ``` +## Boot Blocks ## + +The Macintosh looks for a specific structure in block 0 to decide whether a disk can be booted. +A number of system parameters are stored here, as well as executable code. The format is +documented in IM:Files starting on page 2-57. + +The block 0/1 layout is: + +``` ++$00 / 2: bbID - signature bytes, for HFS this must be $4c $4b ('LK') ++$02 / 4: bbEntry - entry point to boot code, expressed as a 68K BRA.S instruction ++$06 / 2: bbVersion - flag byte and boot block version number ++$08 / 2: bbPageFlags - "used internally" ++$0a /16: bbSysName - system filename, usually "System" (stored as string with leading length byte) ++$1a /16: bbShellName - Finder filename, usually "Finder" ++$2a /16: bbDbg1Name - first debugger filename, usually "MacsBug" ++$3a /16: bbDbg2Name - second debugger filename, usually "Disassembler" ++$4a /16: bbScreenName - file containing startup screen, usually "StartUpScreen" ++$5a /16: bbHelloName - name of startup program, usually "Finder" ++$6a /16: bbScrapName - name of system scrap file, usually "Clipboard" ++$7a / 2: bbCntFCBs - number of FCBs to allocate ++$7c / 2: bbCntEvts - number of event queue elements ++$7e / 4: bb128KSHeap - system heap size on 128K Mac ++$82 / 4: bb256KSHeap - "used internally" ++$86 / 4: bbSysHeapSize - system heap size on machines with >= 512K of RAM ++$8a / 2: filler - reserved ++$8c / 4: bbSysHeapExtra - minimum amount of additional System heap space required ++$90 / 4: bbSysHeapFract - fraction of RAM to make available for system heap ++$94 /nn: executable code, if any +``` + +The last two heap size fields are only present in "new"-style boot blocks. A bit in the version +flags will tell you whether or not they are present. These values override the earlier fields. + +The `bbEntry` value is a 68K branch whose offset is relative to the start of the instruction + 2, +so `60 00 00 86` is a branch to 4 + $86 + 2 = $8c, appropriate for an "old"-style boot block. +A "new"-style boot block should be `60 00 00 8e`, branching to $94. + +The `bbVersion` field is documented as a 16-bit value, but the first (high) byte holds flags, +while the second (low) byte holds the boot block version number. The flags are: + +bit | meaning +--- | ------- +0-4 | reserved, must be 0 + 5 | set if relative system heap sizing is to be used + 6 | set if the boot code in the boot blocks is to be executed + 7 | set if the new boot block header format is used + +If bit 7 is clear (old format), then bits 5 and 6 are ignored, and the boot code is only executed +if the version is 0x0d. If bit 7 is set (new format), then bit 6 determines whether or not the +code is executed. IM:Files notes: + +> Generally, however, the boot code stored on disk is ignored in favor of boot code stored in a +> resource in the System file. + ## Miscellaneous ## HFS volumes can checked with the `fsck.hfs` command. The x86-64 version found on Linux diff --git a/DiskArc/FS/HFS.cs b/DiskArc/FS/HFS.cs index 6badde4..7907fee 100644 --- a/DiskArc/FS/HFS.cs +++ b/DiskArc/FS/HFS.cs @@ -590,9 +590,14 @@ public void Format(string volumeName, int volumeNum, bool makeBootable) { throw new ArgumentException("Invalid volume name"); } - // Zero out the boot blocks. - ChunkAccess.WriteBlock(0, HFS_FileDesc.sZeroBlock, 0); - ChunkAccess.WriteBlock(1, HFS_FileDesc.sZeroBlock, 0); + // Write a Macintosh boot block, or just zero it out. + if (makeBootable && false) { + ChunkAccess.WriteBlock(0, sBootBlock0, 0); + ChunkAccess.WriteBlock(1, sBootBlock1, 0); + } else { + ChunkAccess.WriteBlock(0, HFS_FileDesc.sZeroBlock, 0); + ChunkAccess.WriteBlock(1, HFS_FileDesc.sZeroBlock, 0); + } // Compute geometry. // @@ -1146,6 +1151,80 @@ internal uint AllocBlockToLogiBlock(uint allocBlockNum) { return VolMDB.AllocBlockStart + allocBlockNum * VolMDB.LogicalPerAllocBlock; } + /// + /// Standard Macintosh boot block. Obtained from "bootblockdata" file in + /// . + /// Copyright Apple Computer, Inc. + /// + private static readonly byte[] sBootBlock0 = new byte[512] { + 0x4c,0x4b,0x60,0x00,0x00,0x86,0x44,0x18,0x00,0x00,0x06,0x53,0x79,0x73,0x74,0x65, + 0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x46,0x69,0x6e,0x64,0x65, + 0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x4d,0x61,0x63,0x73,0x42, + 0x75,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x44,0x69,0x73,0x61,0x73, + 0x73,0x65,0x6d,0x62,0x6c,0x65,0x72,0x00,0x00,0x00,0x0d,0x53,0x74,0x61,0x72,0x74, + 0x55,0x70,0x53,0x63,0x72,0x65,0x65,0x6e,0x00,0x00,0x06,0x46,0x69,0x6e,0x64,0x65, + 0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x43,0x6c,0x69,0x70,0x62, + 0x6f,0x61,0x72,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x14,0x00,0x00, + 0x43,0x00,0x00,0x00,0x80,0x00,0x00,0x02,0x00,0x00,0x4a,0x78,0x02,0x8e,0x6b,0x46, + 0x20,0x78,0x02,0xae,0x32,0x28,0x00,0x08,0x7c,0xfe,0x54,0x46,0x30,0x3b,0x60,0x3c, + 0x67,0x58,0xb2,0x40,0x66,0xf4,0x0c,0x01,0x00,0x76,0x62,0x10,0x20,0x78,0x02,0xa6, + 0xd1,0xfa,0xff,0xd4,0xa0,0x57,0x21,0xf8,0x02,0xa6,0x01,0x18,0x58,0x4f,0x2e,0x0f, + 0x61,0x38,0x32,0x3b,0x60,0x22,0x4a,0x40,0x67,0x04,0x32,0x3b,0x60,0x24,0x20,0x78, + 0x02,0xae,0x4e,0xf0,0x10,0x00,0x70,0x62,0xa9,0xc9,0x00,0x75,0x02,0x76,0x01,0x78, + 0x03,0x7a,0x06,0x7c,0x00,0x00,0x0a,0x44,0x09,0x0e,0x0f,0x1c,0x30,0xe6,0x1d,0x96, + 0x0b,0x82,0x0a,0x52,0x11,0xae,0x33,0x6e,0x20,0x3e,0x41,0xfa,0xff,0x0e,0x43,0xf8, + 0x0a,0xd8,0x70,0x10,0xa0,0x2e,0x41,0xfa,0xff,0x12,0x43,0xf8,0x02,0xe0,0x70,0x10, + 0xa0,0x2e,0x41,0xfa,0xff,0x56,0x43,0xf8,0x09,0x70,0x21,0xc9,0x09,0x6c,0x70,0x10, + 0xa0,0x2e,0x30,0x3a,0xff,0x58,0xa0,0x6d,0x30,0x3a,0xff,0x50,0xa0,0x6c,0x20,0x47, + 0x31,0x78,0x02,0x10,0x00,0x16,0xa0,0x0f,0x66,0x54,0x42,0xa8,0x00,0x12,0x42,0x68, + 0x00,0x1c,0xa2,0x07,0x66,0x40,0x28,0x68,0x00,0x5e,0x21,0x68,0x00,0x5a,0x00,0x30, + 0x67,0x10,0x21,0x7c,0x45,0x52,0x49,0x4b,0x00,0x1c,0x70,0x01,0xa2,0x60,0x66,0x26, + 0xa0,0x15,0x55,0x4f,0xa9,0x95,0x4a,0x5f,0x6b,0x1a,0x59,0x4f,0x2f,0x3c,0x62,0x6f, + 0x6f,0x74,0x3f,0x3c,0x00,0x02,0xa9,0xa0,0x20,0x1f,0x67,0x12,0x58,0x4f,0x26,0x40, + 0x20,0x53,0x4e,0xd0,0x70,0x2b,0x3f,0x00,0x20,0x47,0xa0,0x0e,0x30,0x1f,0x4e,0x75, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda + }; + private static readonly byte[] sBootBlock1 = new byte[512] { + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda + }; + #endregion Miscellaneous } }