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 } }