Skip to content

Instantly share code, notes, and snippets.

@joevt
Last active March 16, 2024 10:31
Show Gist options
  • Save joevt/a99e3af71343d8242e0078ab4af39b6c to your computer and use it in GitHub Desktop.
Save joevt/a99e3af71343d8242e0078ab4af39b6c to your computer and use it in GitHub Desktop.
A script to help with diagnosing legacy BIOS boot issues on Macs
#!/bin/bash
#
# Get Partition Info from all disks
#
# Written by joevt updated March 16, 2024
# Patches marked "rgh" July, 2010, to dump information beyond the
# four bios partitions
#
# sudo ./dumpvols.sh > dumpvols_result.txt 2>&1
#
# Based on johnsock's AHCI Master Boot Record Patch.
#
# This script is freely distributable.
#
if [ ! "$USER" = "root" ]; then
echo WARNING: This script must be run as root.
exit
fi
INPUTDISK="$1"
INPUTDISK="${INPUTDISK#/dev/}"
INPUTSLICE=$(expr "$INPUTDISK" : 'disk[0-9]*s\([0-9]*\)')
if [[ -n $INPUTDISK ]]; then
disklist="$(diskutil list "$INPUTDISK" | perl -p -e 's|^/|\n/|')"
apfslist="$(diskutil apfs list | sed -nE "/^\|/s// /; /^ $/s///; /\+.*$1 /,/^$/ { /^$/d ; p ; }" 2> /dev/null)"
ALLDISKS=0
else
disklist="$(diskutil list | perl -p -e 's|^/|\n/|')"
apfslist="$(diskutil apfs list 2> /dev/null)"
ALLDISKS=1
fi
[[ "${apfslist:0:4}" == "Disk" ]] && apfslist=""
MBRHASHES="
Windows_XP=d88d4f2dbc2c662db7d7d60ebf9e3e00
Windows_Vista=12c9d7ff4914c88a7f9eadf9211b861b
Windows_7=118eb70c44cb69284e5d8aa93096831e
None_all_zeros=4ebc676ce4896613a3a9df6e2a1c77ae
MSDOS_or_FreeDOS_on_FreeDOS=93dd2ee87a995e36cbab0c2d5c2f041a
Windows_XP_On_BootCamp2_with_AHCI_patch=c3fb54174bc479899d4ef6e45308dc18
Windows_XP_On_BootCamp2=cb4dabdd862da0508083b05814e198b8
Windows_Vista_on_XP_with_AHCI_patch=4979e1b9d70738759280f6962c2ad298
Windows_7_on_XP=7db43c1425e9ff3077dd62b776a50419
Windows_7_with_AHCI_patch=a243d3475531b0f6f0d7199043c2eb5c
Windows_7_on_XP_with_AHCI_patch=24977c27865adec9ac8298f1a8d214bf
Apple_Partition_Map_Block0_Driver_Descriptor_Map_390721968_blocks_and_Tiger_OS_9_drivers=087f35e49a39d52a46e3a94882869f51
"
#All VBR hashes use all the bytes starting from offset 0x60. It may be better to use a different range for each type of VBR...
# GRUB2 hash was incorrectly named GRUB #rgh
# added GRUB hash from observation of kununtu 9.04 #rgh
# added Windows 8
VBRHASHES="
None_all_zeros=acf496fff71230daa6985a701f83ce49
NTFS_No_Loader=3be27456483746abb85cd614381dac5e
NTFS_Windows_XP_NTLDR=dd1728a59343b9fa9458d80657f68771
NTFS_Windows_Vista_BOOTMGR=d1c278b56eeea9536d0eb5898fe6a0b5
NTFS_Windows_8_BOOTMGR=771df8b803f96296854316d3d5918812
GRUB_from_Ubuntu=332469fa146db809f58d6392e2e0bdce
GRUB2_from_Ubuntu=9c249066e1eb9c842d8acdfe6d23a2e3
FAT32_FRDOS4.1=98050815221ee147066f99f806c23203
FAT32_FRDOS4.1_or_MSWIN4.1_BOOTMGR=aec608de8ac709d91e6f3340b643ab4d
FAT32_NTFS_NTLDR=d9c3d66e975d2b3b122353951a598b32
FAT12_BSD_4.4_BOOTMGR=4cc92970d5a3350bc72d2b975e28b915
FAT16_Non_system_disk=2a3d0f51ad246f115aa7d37891788857
FAT32_Non_system_disk_or_EFI=34f2d1f3c3ecce5c00cae8f0b82c922b
HFS_boot_block_0=28f5bc1563fbaedeb8dabbd4ef9eb4c2
APM_Driver_SCSI_patch=44dc8729f17b4de891fc93d8db04e393
APM_Driver_SCSI_chained_real=f13d0837e944353d07121dcda47f01c0
APM_Driver_ATA_patch=e1dd2732d4f0cfc3f79357f1bae992c7
APM_Driver_ATA_chained_real=4ccc33e59537e50e7831fc499a8672a5
"
# APM drivers created by Leopard Install Mac OS 9 Drivers
FindHash () {
# $1: name of hashed contents
# $2: list of known hashes
# $3: the hash to search for
DIDFIND=0
for CURHASH in $2; do
THEHASH=$(expr "$CURHASH" : '[^=]*=\(.*\)')
THEOS=$(expr "$CURHASH" : '^\([^=]*\)=')
if [ "$3" = "$THEHASH" ]; then
DIDFIND=1
break
fi
done
echo ""
if [ $DIDFIND = 1 ]; then
echo "$1: $THEOS"
else
echo "$1: Unrecognized (hash=$3)"
fi
}
pascalstring () {
# $1 pascal string bytes
local thebytes;
local thechars;
local thelen;
thebytes="$1"
thelen=$((0x${thebytes:0:2}))
thechars=$(sed -E 's/(00)+$//' <<< "${thebytes:2}" | xxd -p -r | tr '\0' '.')
if (( thelen != ${#thechars} )); then
printf "len:%d? " "$thelen"
fi
printf "\"%s\"" "$thechars"
}
GetFileInfo="GetFileInfo"
command -v GetFileInfo > /dev/null 2>&1 || {
GetFileInfo="/Developer/Tools/GetFileInfo"
}
inodetopath () {
"$GetFileInfo" -P "/.vol/$1/$2" 2> /dev/null | sed -nE '/^(file|directory): "(.*)"/s//\2/p'
}
inodestring () {
local deviceid="$1"
local inode="$2"
local thepath;
thepath="$(inodetopath "$deviceid" "$inode")"
printf "%d" "$inode"
[[ -n $thepath ]] && printf " => \"%s\"" "$thepath"
}
forkdatastring () {
local forkdata="$1"
local extentslist
if [[ -n ${forkdata//0/} ]]; then
extentslist=$(
extents="${forkdata:32}"
while [[ -n $extents ]]; do
if ((0x${extents:0:16})); then
printf "(%d,%d)," $((0x${extents:0:8})) $((0x${extents:8:8}))
else
printf ","
fi
extents="${extents:16}"
done
)
printf "logicalSize:%d clumpSize:%d totalBlocks:%d extents:(%s)" $((0x${forkdata:0:16})) $((0x${forkdata:16:8})) $((0x${forkdata:24:8})) "${extentslist%"${extentslist##*[!,]}"}"
fi
}
extentstring () {
extents="$1"
extentslist=$(
while [[ -n $extents ]]; do
if ((0x${extents:0:16})); then
printf "(%d,%d)," $((0x${extents:0:4})) $((0x${extents:4:4}))
else
printf ","
fi
extents="${extents:8}"
done
)
printf "(%s)" "${extentslist%"${extentslist##*[!,]}"}"
}
dumpencoding () {
local message="$1"
local encoding="$2"
((encoding)) && {
printf "%s 0x%08x" "$message" "$encoding"
(( (encoding & 0x656e6300) == 0x656e6300 )) && {
case $((encoding & 0xff)) in
0) printf " = kTextEncodingMacRoman" ;;
1) printf " = kTextEncodingMacJapanese" ;;
2) printf " = kTextEncodingMacChineseTrad" ;;
3) printf " = kTextEncodingMacKorean" ;;
4) printf " = kTextEncodingMacArabic" ;;
5) printf " = kTextEncodingMacHebrew" ;;
6) printf " = kTextEncodingMacGreek" ;;
7) printf " = kTextEncodingMacCyrillic" ;;
9) printf " = kTextEncodingMacDevanagari" ;;
10) printf " = kTextEncodingMacGurmukhi" ;;
11) printf " = kTextEncodingMacGujarati" ;;
12) printf " = kTextEncodingMacOriya" ;;
13) printf " = kTextEncodingMacBengali" ;;
14) printf " = kTextEncodingMacTamil" ;;
15) printf " = kTextEncodingMacTelugu" ;;
16) printf " = kTextEncodingMacKannada" ;;
17) printf " = kTextEncodingMacMalayalam" ;;
18) printf " = kTextEncodingMacSinhalese" ;;
19) printf " = kTextEncodingMacBurmese" ;;
20) printf " = kTextEncodingMacKhmer" ;;
21) printf " = kTextEncodingMacThai" ;;
22) printf " = kTextEncodingMacLaotian" ;;
23) printf " = kTextEncodingMacGeorgian" ;;
24) printf " = kTextEncodingMacArmenian" ;;
25) printf " = kTextEncodingMacChineseSimp" ;;
26) printf " = kTextEncodingMacTibetan" ;;
27) printf " = kTextEncodingMacMongolian" ;;
28) printf " = kTextEncodingMacEthiopic" ;;
29) printf " = kTextEncodingMacCentralEurRoman" ;;
30) printf " = kTextEncodingMacVietnamese" ;;
31) printf " = kTextEncodingMacExtArabic" ;;
33) printf " = kTextEncodingMacSymbol" ;;
34) printf " = kTextEncodingMacDingbats" ;;
35) printf " = kTextEncodingMacTurkish" ;;
36) printf " = kTextEncodingMacCroatian" ;;
37) printf " = kTextEncodingMacIcelandic" ;;
38) printf " = kTextEncodingMacRomanian" ;;
39) printf " = kTextEncodingMacCeltic" ;;
40) printf " = kTextEncodingMacGaelic" ;;
41) printf " = kTextEncodingMacKeyboardGlyphs" ;;
esac
}
printf "\n"
}
}
command -v python > /dev/null 2>&1 && python=python || python=python3
vsdbtouuid0 () {
"$python" -c '
import uuid ; from hashlib import md5
kFSUUIDNamespaceSHA1 = uuid.UUID("b3e20f39-f292-11d6-97a4-00306543ecac")
digest = md5(kFSUUIDNamespaceSHA1.bytes + bytes.fromhex("'"$1"'"), usedforsecurity=False).digest()
print ("%s" % uuid.UUID(bytes=digest[:16], version=3))
'
}
vsdbtouuid () {
local theuuid=""
theuuid=$(printf "b3e20f39f29211d697a400306543ecac%s" "$1" | xxd -p -r | md5 | tr "a-f" "A-F" )
printf "%s" "${theuuid:0:8}-${theuuid:8:4}-3${theuuid:13:3}-$(printf "%X" $(((0x${theuuid:16:1} & 3) | 8)))${theuuid:17:3}-${theuuid:20:12}"
}
(( ALLDISKS )) && echo "$disklist"
echo "$apfslist"
DRIVELIST="$(sed -n -E "/^[ ]*0: [ ]{0,25}([A-Za-z_]+)[ ]*[+*][0-9.]+ [TGMK][iB][ ]+(disk[0-9]+)$/s//\1_\2/p;/^[ ]*0: [ ]{0,26} .* \*[0-9.]+ [TGMK][iB][ ]+(disk[0-9]+)$/s//whole_\1/p" <<< "$disklist")"
for PARTDRIVE in $(echo $DRIVELIST); do
DRIVE=$(expr "$PARTDRIVE" : '.*_\([^_]*\)')
DTYPE=$(expr "$PARTDRIVE" : '\(.*\)_[^_]*')
echo "==============================================================================="
diskutiloutput="$(sed -nE '/\/dev\/'"$DRIVE"'( |$)/,/^$/ p' <<< "${disklist}")"
echo "$diskutiloutput"
echo "---------------------------------------------"
diskinfo="$(diskutil info "$DRIVE")"
echo "$diskinfo"
BLOCKSIZE=$(sed -nE '/^ *Device Block Size: +([0-9]+).*/s//\1/p' <<< "$diskinfo")
if [[ -z $BLOCKSIZE ]]; then
BLOCKSIZE=512
fi
MOUNTPOINTS=""
if [[ -n $INPUTSLICE ]]; then
DEVLIST="$(echo "$diskutiloutput" | sed -n -E "/^.* (disk[0-9]+s${INPUTSLICE})$/s//\1/p")"
else
DEVLIST="$(echo "$diskutiloutput" | sed -n -E "/^.* (disk[0-9]+s[0-9]+)$/s//\1/p")"
fi
for THEDEV in $(echo $DEVLIST); do
echo "---------------------------------------------"
partinfo="$(diskutil info "$THEDEV")"
echo "$partinfo"
MOUNTPOINTS="${MOUNTPOINTS}${THEDEV}_$(sed -nE '/ *Mount Point: *(.*)/s//\1/p' <<< "$partinfo")"$'\n'
done
echo "---------------------------------------------"
PARTLIST=""
blockbytes=$(dd if="/dev/$DRIVE" bs=512 count=1 2> /dev/null | xxd -p -c 9999)
if [ "$DTYPE" = "Apple_partition_scheme" ]; then
pdiskoutput="$(pdisk -r -l "/dev/$DRIVE" 2>&1)"
pdiskoutput2="$(pdisk -r -l -f "/dev/$DRIVE" 2>&1)"
echo "$pdiskoutput"
[[ "$pdiskoutput" != "$pdiskoutput2" ]] && echo "$pdiskoutput2"
i=0
if [[ ${blockbytes:0:4} == "4552" ]]; then # 'ER'
sbBlkSize=$((0x${blockbytes:4:4}))
sbBlkCount=$((0x${blockbytes:8:8}))
sbDevType=$((0x${blockbytes:16:4}))
sbDevId=$((0x${blockbytes:20:4}))
sbData=$((0x${blockbytes:24:8}))
sbDrvrCount=$((0x${blockbytes:32:4}))
echo
echo "APM Block 0 contents"
printf "000: sbSig : 'ER' = sbSIGWord\n"
printf "002: sbBlkSize : %d\n" "$sbBlkSize"
printf "004: sbBlkCount : %d = %d MB\n" "$sbBlkCount" $((sbBlkCount*sbBlkSize / 1000 / 1000))
((sbDevType != 0)) && printf "008: sbDevType : %d\n" "$sbDevType"
((sbDevId != 0)) && printf "00a: sbDevId : %d\n" "$sbDevId"
((sbData != 0)) && printf "00c: sbData : %d\n" "$sbData"
((sbDrvrCount > 10)) && printf "010: sbDrvrCount: %d\n" "$sbDrvrCount"
for ((i=0; i < sbDrvrCount; i++)); do
ddBlock=$((0x${blockbytes:36+i*16:8}))
ddSize=$((0x${blockbytes:44+i*16:4}))
ddType=$((0x${blockbytes:48+i*16:4}))
printf "%03x: DDMap[%d]:%4d @ %-4d 0x%04x = %-27s\n" $((0x012 + i*8)) "$i" "$ddSize" "$ddBlock" "$ddType" "$(
{
((ddType == 0x0001)) && printf "kDriverTypeMacSCSI" ; } ||
{
((ddType == 0x0701)) && printf "kDriverTypeMacATA" ; } ||
{
((ddType == 0xFFFF)) && printf "kDriverTypeMacSCSIChained"; } ||
{
((ddType == 0xF8FF)) && printf "kDriverTypeMacATAChained" ; } ||
printf "?"
)"
done
ddPad="${blockbytes:52+i*16}"
[[ -n ${ddPad//0/} ]] && printf "ddPad: %s\n" "$ddPad"
echo
xxd -p -r <<< "$blockbytes" | xxd -c 16
else
# use the same bytes as MBR hash even though Block0 contents are totally different
HASH=$(xxd -p -r <<< "${blockbytes:0:440*2}" | xxd -p | md5)
FindHash "Block0 contents" "$MBRHASHES" "$HASH"
xxd -p -r <<< "$blockbytes" | xxd -c 16
fi
PARTTYPE="APM"
PARTLIST=$(echo "$pdiskoutput" | sed -nE "/ *[0-9]+: +Apple_Free /d; /[0-9]+: +[0-9]+ @ [0-9]+, type=0x/d; / *([0-9]+): +([^ ]+) .* ([0-9]+) @ ([0-9]+).*/s//\1_\4_\3_\2/p")
elif [ "$DTYPE" = "GUID_partition_scheme" ] || [ "$DTYPE" = "FDisk_partition_scheme" ]; then
gptoutput="$(gpt -r show "$DRIVE" 2>&1)"
gptoutput2="$(gpt -r show -l "$DRIVE" 2>&1)"
fdiskoutput="$(fdisk "/dev/r$DRIVE")"
echo
echo "$gptoutput"
! grep -q "illegal option -- l" <<< "$gptoutput2" && {
echo
echo "$gptoutput2"
}
echo
echo "$fdiskoutput"
HASH=$(xxd -p -r <<< "${blockbytes:0:440*2}" | xxd -p | md5)
FindHash "MBR contents" "$MBRHASHES" "$HASH"
xxd -p -r <<< "$blockbytes" | xxd -c 16
if [ "$DTYPE" = "FDisk_partition_scheme" ]; then
PARTLIST=$(echo "$fdiskoutput" | sed -n -E "/^[ \*]+([0-9])\: ([0-9A-F]{2}) .*\[[ ]*([0-9]+) \-[ ]+([1-9][0-9]*)\].*$/s//\1_\3_\4_\2/p")
PARTTYPE="MBR"
else
blockbytes=$(dd if="/dev/$DRIVE" bs="$BLOCKSIZE" skip=1 count=1 2> /dev/null | xxd -p -c 9999)
HASH=$(xxd -p -r <<< "${blockbytes:96*2:416*2}" | xxd -p | md5)
FindHash "GPT Header @ 1: GPT Header contents" "$VBRHASHES" "$HASH"
xxd -p -r <<< "$blockbytes" | xxd -c 16
PARTLIST=$(echo "$gptoutput" | sed -n -E "/^[ ]+([0-9]+)[ ]+([0-9]+)[ ]+([0-9]+)[ ]+GPT part \- (.*)$/s//\3_\1_\2_\4/p")
PARTTYPE="GPT"
fi
elif [ "$DTYPE" = "whole" ]; then
HASH=$(xxd -p -r <<< "${blockbytes:0:416*2}" | xxd -p | md5)
FindHash "0 @ 0: VBR contents" "$VBRHASHES" "$HASH"
xxd -p -r <<< "$blockbytes" | xxd -c 16
else
echo "Unknown partition scheme"
fi
if [[ -n $INPUTSLICE ]]; then
PARTLIST="$(sed -nE "/^${INPUTSLICE}_/p" <<< "$PARTLIST")"
fi
for THEPART in $(echo $PARTLIST); do
PNUM=$( expr "$THEPART" : '\([0-9]*\)_')
PSTART=$( expr "$THEPART" : '[0-9]*_\([0-9]*\)_[0-9]*')
PLENGTH=$(expr "$THEPART" : '[0-9]*_[0-9]*_\([0-9]*\)')
PTYPE=$( expr "$THEPART" : '[0-9]*_[0-9]*_[0-9]*_\(.*\)')
DEVICEID=$(stat -f "%r" "/dev/${DRIVE}s$PNUM")
POFFSETS="_0"
while [[ -n $POFFSETS ]]; do
POFFSET=$( expr "$POFFSETS" : '_\([0-9]*\)')
POFFSETS=$( expr "$POFFSETS" : '_[0-9]*\(_.*\)')
if (( POFFSET >= PLENGTH )); then
continue
fi
blockbytes=$(dd if="/dev/$DRIVE" bs="$BLOCKSIZE" skip=$((PSTART + POFFSET)) count=1 2> /dev/null | xxd -p -c 9999)
if [[ $PTYPE = "Apple_Patches" ]]; then
# Patches # https://developer.apple.com/library/archive/technotes/tn/tn1189.html#SecretsOfThePartitionMap
echo
echo "$PARTTYPE $PNUM @ ${PSTART}$( ((POFFSET > 0)) && printf "+%d" "$POFFSET" ): Driver Patches"
numPatchBlocks=$((0x${blockbytes:0:4}))
numPatches=$((0x${blockbytes:4:4}))
printf "000: numPatchBlocks: %d\n" "$numPatchBlocks"
byteoffset=4;
for (( i=0; i < numPatches; i++ )); do
printf "%03x: PatchDescriptor[%d]:\n" "$byteoffset" "$i"
patchSig=$(sed -E 's/(00)+$//' <<< "${blockbytes:$byteoffset*2:8}" | xxd -p -r | tr '\0' '.')
majorVers=$((0x${blockbytes:$byteoffset*2+8:4}));
minorVers=$((0x${blockbytes:$byteoffset*2+12:4}));
flags=$((0x${blockbytes:$byteoffset*2+16:8}));
patchOffset=$((0x${blockbytes:$byteoffset*2+24:8}));
patchSize=$((0x${blockbytes:$byteoffset*2+32:8}));
patchCRC=$((0x${blockbytes:$byteoffset*2+40:8}));
patchDescriptorLen=$((0x${blockbytes:$byteoffset*2+48:8}));
patchNameLen=$((0x${blockbytes:$byteoffset*2+56:2}));
patchName=$(pascalstring "${blockbytes:$byteoffset*2+56:$patchNameLen*2+2}")
patchVendorLen=$((0x${blockbytes:$byteoffset*2+122:2}));
patchVendor=$(pascalstring "${blockbytes:$byteoffset*2+122:$patchVendorLen*2+2}")
patchPad="${blockbytes:$byteoffset*2+124+$patchVendorLen*2:$patchDescriptorLen*2 - (124+$patchVendorLen*2)}"
printf "%03x: patchSig : '%s'\n" $((byteoffset+ 0)) "$patchSig"
printf "%03x: majorVers : %d\n" $((byteoffset+ 4)) "$majorVers"
printf "%03x: minorVers : %d\n" $((byteoffset+ 6)) "$minorVers"
printf "%03x: flags : 0x%08x" $((byteoffset+ 8)) "$flags"
if (( flags )); then
flagtext=$(
((flags & 1)) && printf ",kRequiredPatch"
((flags & ~1)) && printf ",0x%08x?" $((flags & ~1))
)
printf " = %s" "${flagtext:1}"
fi
printf "\n"
printf "%03x: patchOffset : %d\n" $((byteoffset+12)) "$patchOffset"
printf "%03x: patchSize : %d\n" $((byteoffset+16)) "$patchSize"
printf "%03x: patchCRC : 0x%08x\n" $((byteoffset+20)) "$patchCRC"
printf "%03x: patchDescriptorLen : %d\n" $((byteoffset+24)) "$patchDescriptorLen"
printf "%03x: patchName : %s\n" $((byteoffset+28)) "$patchName"
printf "%03x: patchVendor : %s\n" $((byteoffset+61)) "$patchVendor"
[[ -n $patchPad ]] && printf "%03x: patchPad : %s\n" $((byteoffset+62+patchVendorLen)) "$patchPad"
((byteoffset+=patchDescriptorLen))
done # for numPatches
echo
xxd -p -r <<< "$blockbytes" | xxd -c 16
elif [[ ${blockbytes:0:4} == "504d" ]]; then # 'PM'
first_pmMapBlkCnt=$((0x${blockbytes:8:8}))
echo
echo "$PARTTYPE $PNUM @ ${PSTART}$( ((POFFSET > 0)) && printf "+%d" "$POFFSET" ): Partition Map contents (${first_pmMapBlkCnt} partitions)"
for ((i=0;i<PLENGTH;i++)); do
if (( i > 0 )); then
blockbytes=$(dd if="/dev/$DRIVE" bs="$BLOCKSIZE" skip=$((PSTART + POFFSET + i)) count=1 2> /dev/null | xxd -p -c 9999)
fi
if [[ -n ${blockbytes//0/} ]]; then
# Partition
pmSig="${blockbytes:0:4}"
pmSigPad=$((0x${blockbytes:4:4}))
pmMapBlkCnt=$((0x${blockbytes:8:8}))
pmPyPartStart=$((0x${blockbytes:16:8}))
pmPartBlkCnt=$((0x${blockbytes:24:8}))
pmPartName=$(sed -E 's/(00)+$//' <<< "${blockbytes:32:64}" | xxd -p -r | tr '\0' '.')
pmParType=$(sed -E 's/(00)+$//' <<< "${blockbytes:96:64}" | xxd -p -r | tr '\0' '.')
pmLgDataStart=$((0x${blockbytes:160:8}))
pmDataCnt=$((0x${blockbytes:168:8}))
pmPartStatus=$((0x${blockbytes:176:8}))
pmLgBootStart=$((0x${blockbytes:184:8}))
pmBootSize=$((0x${blockbytes:192:8}))
pmBootAddr=$((0x${blockbytes:200:8}))
pmBootAddr2=$((0x${blockbytes:208:8}))
pmBootEntry=$((0x${blockbytes:216:8}))
pmBootEntry2=$((0x${blockbytes:224:8}))
pmBootCksum=$((0x${blockbytes:232:8}))
pmProcessor=$(sed -E 's/(00)+$//' <<< "${blockbytes:240:32}" | xxd -p -r | tr '\0' '.')
pmPad1="${blockbytes:272:256}"
pmPad2=$(sed -E 's/(00)+$//' <<< "${blockbytes:528}")
printf "%2d:" "$((i+1))"
printf " %10d @ %-10d" \
"$pmPartBlkCnt" \
"$pmPyPartStart"
[[ $pmSig != 504d ]] && printf " Sig:0x%s?" "$pmSig"
[[ -n $pmParType ]] && printf " Type:\"%s\"" "$pmParType"
[[ -n $pmPartName ]] && printf " Name:\"%s\"" "$pmPartName"
(( pmSigPad )) && printf " SigPad:0x%04X" "$pmSigPad"
(( pmMapBlkCnt != first_pmMapBlkCnt )) && printf " MapBlkCnt:%d" "$pmMapBlkCnt"
(( pmLgDataStart )) && printf " LgDataStart:%d" "$pmLgDataStart"
blockbytes2=${blockbytes:160}
if [[ -n ${blockbytes2//0/} ]]; then
(( pmDataCnt != pmPartBlkCnt )) && printf " DataCnt:%d" "$pmDataCnt"
(( pmPartStatus )) && {
statustext=$(
(( pmPartStatus & 0x00000001 )) && printf ",Valid" # AUX
(( pmPartStatus & 0x00000002 )) && printf ",Allocated" # AUX
(( pmPartStatus & 0x00000004 )) && printf ",InUse" # AUX
(( pmPartStatus & 0x00000008 )) && printf ",Bootable" # AUX
(( pmPartStatus & 0x00000010 )) && printf ",Readable" # AUX
(( pmPartStatus & 0x00000020 )) && printf ",Writeable" # AUX and Mac OS
(( pmPartStatus & 0x00000040 )) && printf ",BootCodePositionIndependent" # AUX
(( pmPartStatus & 0x00000080 )) && printf ",OSSpecific2" # ?
(( pmPartStatus & 0x00000100 )) && printf ",ChainCompatible" # driver
(( pmPartStatus & 0x00000200 )) && printf ",RealDeviceDriver" # driver
(( pmPartStatus & 0x00000400 )) && printf ",CanChainToNext" # driver
(( pmPartStatus & 0x40000000 )) && printf ",MountedAtStartup" # Mac OS
(( pmPartStatus & 0x80000000 )) && printf ",Startup" # Mac OS
(( pmPartStatus & 0x3FFFF800 )) && printf ",0x%x?" $((pmPartStatus & 0x3FFFF800))
)
printf " Status:%08X=%s" "$pmPartStatus" "${statustext:1}"
}
(( pmLgBootStart )) && printf " LgBootStart:%d" "$pmLgBootStart"
(( pmBootSize )) && printf " BootSize:%d" "$pmBootSize"
(( pmBootAddr )) && printf " BootAddr:0x%08X" "$pmBootAddr"
(( pmBootAddr2 )) && printf " BootAddr2:0x%08X" "$pmBootAddr2"
(( pmBootEntry )) && printf " BootEntry:0x%08X" "$pmBootEntry"
(( pmBootEntry2 )) && printf " BootEntry2:0x%08X" "$pmBootEntry2"
(( pmBootCksum )) && printf " BootCksum:0x%08X" "$pmBootCksum"
[[ -n $pmProcessor ]] && printf " Processor:\"%s\"" "$pmProcessor"
[[ -n ${pmPad1//0/} ]] && {
printf " Pad1:%s" "$(sed -E 's/(00)+$//' <<< "${pmPad1}")"
[ "${pmPad1:0:8}" = 70744452 ] && printf " = 'ptDR' = kPatchDriverSignature"
[ "${pmPad1:0:8}" = 00010600 ] && printf "00 = kSCSIDriverSignature"
[ "${pmPad1:0:8}" = 77696b69 ] && printf " = 'wiki' = kATADriverSignature"
[ "${pmPad1:0:8}" = 43447672 ] && printf " = 'CDvr' = kSCSICDDriverSignature"
[ "${pmPad1:0:8}" = 41545049 ] && printf " = 'ATPI' = kATAPIDriverSignature"
[ "${pmPad1:0:8}" = 44535531 ] && printf " = 'DSU1' = kDriveSetupHFSSignature"
}
[[ -n $pmPad2 ]] && printf " Pad2:%s" "$pmPad2"
fi
printf "\n"
fi
done # for APM block
elif [[ ${blockbytes:0:4} == "4c4b" ]]; then # 'LK'
# Boot Blocks # https://developer.apple.com/library/archive/documentation/mac/pdf/Files/File_Manager.pdf
# BootBlkHdr
#bbID=$((0x${blockbytes:0:4}))
bbEntry=$((0x${blockbytes:4:8}))
bbVersion=$((0x${blockbytes:12:4}))
bbPageFlags=$((0x${blockbytes:16:4}))
bbSysName=$( pascalstring "${blockbytes:20:32}" )
bbShellName=$( pascalstring "${blockbytes:52:32}" )
bbDbg1Name=$( pascalstring "${blockbytes:84:32}" )
bbDbg2Name=$( pascalstring "${blockbytes:116:32}" )
bbScreenName=$(pascalstring "${blockbytes:148:32}" )
bbHelloName=$( pascalstring "${blockbytes:180:32}" )
bbScrapName=$( pascalstring "${blockbytes:212:32}" )
bbCntFCBs=$((0x${blockbytes:244:4}))
bbCntEvts=$((0x${blockbytes:248:4}))
bb128KSHeap=$((0x${blockbytes:252:8}))
bb256KSHeap=$((0x${blockbytes:260:8}))
bbSysHeapSize=$((0x${blockbytes:268:8}))
filler=$((0x${blockbytes:276:4}))
bbSysHeapExtra=$((0x${blockbytes:280:8}))
bbSysHeapFract=$((0x${blockbytes:288:8}))
echo
echo "$PARTTYPE $PNUM @ ${PSTART}$( ((POFFSET > 0)) && printf "+%d" "$POFFSET" ): Boot Block Header contents"
CODESTART=$((0x94))
printf "000: bbID : 'LK'\n"
printf "002: bbEntry : 0x%08x" "$bbEntry"
if (( (bbEntry & 0xffff0000) == 0x60000000 )); then
CODESTART=$(((bbEntry & 0xffff) + 4))
printf " = BRA.S *+$%X to offset 0x%03x" $(( CODESTART - 2)) "$CODESTART"
(( CODESTART - 2 == 0x8a )) && printf " (after old header)"
(( CODESTART - 2 == 0x94 )) && printf " (after new header)"
fi
printf "\n"
printf "006: bbVersion : 0x%04x" "$bbVersion"
(( bbVersion )) && {
printf " ="
(( bbVersion & 0xff00 )) && {
printf " flags:("
if (( bbVersion & 0x8000 )); then
printf "new header"
(( bbVersion & 0x4000 )) && printf ", execute boot code"
(( bbVersion & 0x2000 )) && printf ", use relative system heap - bbSysHeapExtra and bbSysHeapFract instead of bbSysHeapSize"
(( bbVersion & 0x1f00 )) && printf ", 0x%02x?" $(( (bbVersion & 0x1f00) >> 8 ))
else
printf "old header"
(( bbVersion & 0x7f00 )) && printf ", 0x%02x?" $(( (bbVersion & 0x7f00) >> 8 ))
fi
printf ")"
}
(( bbVersion & 0xff )) && {
(( bbVersion & 0xff00 )) && printf ","
printf " version:%d.%d:(" $(( (bbVersion >> 4) & 15 )) $(( bbVersion & 15 ))
(( (bbVersion & 0xff) < 0x15 )) && printf "ignore bb128KSHeap and bb256KSHeap and use default of bbSysHeapSize"
(( (bbVersion & 0xff) >= 0x15 )) && printf "use bbSysHeapSize" # How is this different than < 0x15? the documentation for this is bad
(( (bbVersion & 0xff) == 0xD )) && printf ", don't execute boot code" # I don't know if this is correct; the documentation for this is bad
printf ")"
}
printf "\n"
}
((bbPageFlags)) && {
# https://developer.apple.com/library/archive/technotes/dv/dv_03.html#//apple_ref/doc/uid/DTS10002393
printf "008: bbPageFlags : 0x%04x =" "$bbPageFlags"
if ((bbPageFlags & 0x8000)); then
printf "allocate both video and sound buffers"
else
((bbPageFlags > 0)) && printf "allocate only the secondary sound buffer"
fi
printf "\n"
}
printf "00a: bbSysName : %s\n" "$bbSysName"
printf "01a: bbShellName : %s\n" "$bbShellName"
printf "02a: bbDbg1Name : %s\n" "$bbDbg1Name"
printf "03a: bbDbg2Name : %s\n" "$bbDbg2Name"
printf "04a: bbScreenName : %s\n" "$bbScreenName"
printf "05a: bbHelloName : %s\n" "$bbHelloName"
printf "06a: bbScrapName : %s\n" "$bbScrapName"
printf "07a: bbCntFCBs : %d\n" "$bbCntFCBs"
printf "07c: bbCntEvts : %d\n" "$bbCntEvts"
printf "07e: bb128KSHeap : %d\n" "$bb128KSHeap"
printf "082: bb256KSHeap : %d\n" "$bb256KSHeap"
printf "086: bbSysHeapSize : %d\n" "$bbSysHeapSize"
((CODESTART > 0x8a)) && printf "08a: filler : 0x%08x\n" "$filler"
((CODESTART > 0x8c)) && printf "08c: bbSysHeapExtra: 0x%08x\n" "$bbSysHeapExtra"
((CODESTART > 0x90)) && printf "090: bbSysHeapFract: 0x%08x\n" "$bbSysHeapFract"
printf "%03x: boot code\n" "$CODESTART"
echo
xxd -p -r <<< "$blockbytes" | xxd -c 16
((POFFSET++))
blockbytes=$(dd if="/dev/$DRIVE" bs="$BLOCKSIZE" skip=$((PSTART + POFFSET)) count=1 2> /dev/null | xxd -p -c 9999)
echo
echo "$PARTTYPE $PNUM @ ${PSTART}$( ((POFFSET > 0)) && printf "+%d" "$POFFSET" ): 2nd Boot Block contents"
xxd -p -r <<< "$blockbytes" | xxd -c 16
((POFFSET++))
POFFSETS="_${POFFSET}${POFFSETS}"
#printf "queued first MDB after boot blocks: $POFFSETS\n"
elif [[ ${blockbytes:0:4} == "4244" ]]; then # 'BD'
# Master Directory Blocks # https://developer.apple.com/library/archive/documentation/mac/pdf/Files/File_Manager.pdf
# MDB
#drSigWord=${blockbytes:0x000*2:4}
drCrDate=$((0x${blockbytes:0x002*2:8}))
drLsMod=$((0x${blockbytes:0x006*2:8}))
drAtrb=$((0x${blockbytes:0x00a*2:4}))
drNmFls=$((0x${blockbytes:0x00c*2:4}))
drVBMSt=$((0x${blockbytes:0x00e*2:4}))
drAllocPtr=$((0x${blockbytes:0x010*2:4}))
drNmAlBlks=$((0x${blockbytes:0x012*2:4}))
drAlBlkSiz=$((0x${blockbytes:0x014*2:8}))
drClpSiz=$((0x${blockbytes:0x018*2:8}))
drAlBlSt=$((0x${blockbytes:0x01c*2:4}))
drNxtCNID=$((0x${blockbytes:0x01e*2:8}))
drFreeBks=$((0x${blockbytes:0x022*2:4}))
drVN="$(pascalstring "${blockbytes:0x024*2:28*2}")"
drVolBkUp=$((0x${blockbytes:0x040*2:8}))
drVSeqNum=$((0x${blockbytes:0x044*2:4}))
drWrCnt=$((0x${blockbytes:0x046*2:8}))
drXTClpSiz=$((0x${blockbytes:0x04a*2:8}))
drCTClpSiz=$((0x${blockbytes:0x04e*2:8}))
drNmRtDirs=$((0x${blockbytes:0x052*2:4}))
drFilCnt=$((0x${blockbytes:0x054*2:8}))
drDirCnt=$((0x${blockbytes:0x058*2:8}))
drFndrInfo="${blockbytes:0x05c*2:64}"
drVCSize=$((0x${blockbytes:0x07c*2:4}))
drVBMCSize=$((0x${blockbytes:0x07e*2:4}))
drCtlCSize=$((0x${blockbytes:0x080*2:4}))
drEmbedSigWord="$drVCSize"
drEmbedExtent_startBlock="$drVBMCSize"
drEmbedExtent_blockCount="$drCtlCSize"
drXTFlSize=$((0x${blockbytes:0x082*2:8}))
drXTExtRec="${blockbytes:0x086*2:24}"
drCTFlSize=$((0x${blockbytes:0x092*2:8}))
drCTExtRec="${blockbytes:0x096*2:24}"
echo
echo "$PARTTYPE $PNUM @ ${PSTART}$( ((POFFSET > 0)) && printf "+%d" "$POFFSET" ): Master Directory Block contents"
printf "000: drSigWord : 'BD' = kHFSSigWord\n"
printf "002: drCrDate : %s\n" "$( ((drCrDate)) && date -r $((drCrDate-2082844800)))"
printf "006: drLsMod : %s\n" "$( ((drLsMod )) && date -r $((drLsMod -2082844800)))"
((drAtrb)) && {
attributestext=$(
((drAtrb & 0x0080)) && printf ",VolumeHardwareLock"
((drAtrb & 0x0100)) && printf ",VolumeUnmounted"
((drAtrb & 0x0200)) && printf ",VolumeSparedBlocks"
((drAtrb & 0x0400)) && printf ",VolumeNoCacheRequired"
((drAtrb & 0x0800)) && printf ",BootVolumeInconsistent"
((drAtrb & 0x1000)) && printf ",CatalogNodeIDsReused"
((drAtrb & 0x2000)) && printf ",VolumeJournaled"
((drAtrb & 0x4000)) && printf ",VolumeInconsistent"
((drAtrb & 0x8000)) && printf ",VolumeSoftwareLock"
((drAtrb & 0x007f)) && printf ",0x%04x?" $((drAtrb & 0x007f))
)
printf "00a: drAtrb : 0x%04x = %s\n" "$drAtrb" "${attributestext:1}"
}
printf "00c: drNmFls : %d\n" "$drNmFls"
printf "00e: drVBMSt : %d\n" "$drVBMSt"
printf "010: drAllocPtr : %d\n" "$drAllocPtr"
printf "012: drNmAlBlks : %d\n" "$drNmAlBlks"
printf "014: drAlBlkSiz : %d\n" "$drAlBlkSiz"
printf "018: drClpSiz : %d\n" "$drClpSiz"
printf "01c: drAlBlSt : %d\n" "$drAlBlSt"
printf "01e: drNxtCNID : %d\n" "$drNxtCNID"
printf "022: drFreeBks : %d\n" "$drFreeBks"
printf "024: drVN : %s\n" "$drVN"
printf "040: drVolBkUp : %s\n" "$( ((drVolBkUp)) && date -r $((drVolBkUp-2082844800)))"
printf "044: drVSeqNum : %d\n" "$drVSeqNum"
printf "046: drWrCnt : %d\n" "$drWrCnt"
printf "04a: drXTClpSiz : %d\n" "$drXTClpSiz"
printf "04e: drCTClpSiz : %d\n" "$drCTClpSiz"
printf "052: drNmRtDirs : %d\n" "$drNmRtDirs"
printf "054: drFilCnt : %d\n" "$drFilCnt"
printf "058: drDirCnt : %d\n" "$drDirCnt"
printf "05c: drFndrInfo:\n"
printf "05c: Blessed System Folder : %s\n" "$(inodestring "$DEVICEID" "$((0x${drFndrInfo: 0: 8}))" )"
printf "060: Blessed System File : %s\n" "$(inodestring "$DEVICEID" "$((0x${drFndrInfo: 8: 8}))" )"
printf "064: Open-folder linked list : %s\n" "$(inodestring "$DEVICEID" "$((0x${drFndrInfo:16: 8}))" )"
printf "068: Alternate OS blessed file/folder : %s\n" "$(inodestring "$DEVICEID" "$((0x${drFndrInfo:24: 8}))" )"
dumpencoding "06c: Text encoding :" "$((0x${drFndrInfo:32: 8}))"
printf "070: OS X blessed folder : %s\n" "$(inodestring "$DEVICEID" "$((0x${drFndrInfo:40: 8}))" )"
printf "074: 64-bit VSDB volume id : 0x%016X => Volume UUID: %s\n" $((0x${drFndrInfo:48:16})) "$(vsdbtouuid "${drFndrInfo:48:16}")"
if (( drEmbedSigWord == 0x482b )); then
printf "07c: drEmbedSigWord: %d = 'H+' = kHFSPlusSigWord\n" "$drEmbedSigWord"
printf "07e: drEmbedExtent.startBlock : %d\n" "$drEmbedExtent_startBlock"
printf "080: drEmbedExtent.blockCount : %d\n" "$drEmbedExtent_blockCount"
else
printf "07c: drVCSize : %d\n" "$drVCSize"
printf "07e: drVBMCSize : %d\n" "$drVBMCSize"
printf "080: drCtlCSize : %d\n" "$drCtlCSize"
fi
printf "082: drXTFlSize : %d\n" "$drXTFlSize"
printf "086: drXTExtRec : %s\n" "$(extentstring "$drXTExtRec")"
printf "092: drCTFlSize : %d\n" "$drCTFlSize"
printf "096: drCTExtRec : %s\n" "$(extentstring "$drCTExtRec")"
echo
xxd -p -r <<< "$blockbytes" | xxd -c 16
if ((POFFSET < drNmAlBlks * (drAlBlkSiz / 512) - 2)); then
# queue up location of alternate Master Directory Block
POFFSETS="_$((PLENGTH-2))_$((PLENGTH-1))${POFFSETS}"
#printf "queued 2alternate MDB: $POFFSETS \n"
if (( drEmbedSigWord == 0x482b )); then
# queue up location of wrapped HFS+ partition
hfsplusblock=$(( drAlBlSt + drEmbedExtent_startBlock * (drAlBlkSiz / 512) ))
POFFSETS="${POFFSETS}_$((hfsplusblock))_$((hfsplusblock+1))_$((hfsplusblock+2))"
#printf "queued 3wrapped: $POFFSETS \n"
fi
fi
elif [[ ${blockbytes:0:4} == "482b" ]] || [[ ${blockbytes:0:4} == "4858" ]]; then # 'H+' or 'HX'
# Master Directory Blocks # https://developer.apple.com/library/archive/documentation/mac/pdf/Files/File_Manager.pdf
# HFS Plus Volume Header
signature=$((0x${blockbytes:0x000*2:4}))
signatureChars=$(sed -E 's/(00)+$//' <<< "${blockbytes:0x000*2:4}" | xxd -p -r | tr '\0' '.')
version=$((0x${blockbytes:0x002*2:4}))
attributes=$((0x${blockbytes:0x004*2:8}))
lastMountedVersion=$((0x${blockbytes:0x008*2:8}))
lastMountedVersionChars=$(sed -E 's/(00)+$//' <<< "${blockbytes:0x008*2:8}" | xxd -p -r | tr '\0' '.')
journalInfoBlock=$((0x${blockbytes:0x00c*2:8}))
createDate=$((0x${blockbytes:0x010*2:8}))
modifyDate=$((0x${blockbytes:0x014*2:8}))
backupDate=$((0x${blockbytes:0x018*2:8}))
checkedDate=$((0x${blockbytes:0x01c*2:8}))
fileCount=$((0x${blockbytes:0x020*2:8}))
folderCount=$((0x${blockbytes:0x024*2:8}))
blockSize=$((0x${blockbytes:0x028*2:8}))
totalBlocks=$((0x${blockbytes:0x02c*2:8}))
freeBlocks=$((0x${blockbytes:0x030*2:8}))
nextAllocation=$((0x${blockbytes:0x034*2:8}))
rsrcClumpSize=$((0x${blockbytes:0x038*2:8}))
dataClumpSize=$((0x${blockbytes:0x03c*2:8}))
nextCatalogID=$((0x${blockbytes:0x040*2:8}))
writeCount=$((0x${blockbytes:0x044*2:8}))
encodingsBitmap=$((0x${blockbytes:0x048*2:16}))
finderInfo="${blockbytes:0x050*2:64}"
allocationFile="${blockbytes:0x070*2:160}"
extentsFile="${blockbytes:0x0c0*2:160}"
catalogFile="${blockbytes:0x110*2:160}"
attributesFile="${blockbytes:0x160*2:160}"
startupFile="${blockbytes:0x1b0*2:160}"
echo
echo "$PARTTYPE $PNUM @ ${PSTART}$( ((POFFSET > 0)) && printf "+%d" "$POFFSET" ): HFS Plus Volume Header contents"
printf "000: signature : '%s'" "$signatureChars"
((signature == 0x482b )) && printf " = kHFSPlusSigWord"
((signature == 0x4858 )) && printf " = kHFSXSigWord"
printf "\n"
printf "002: version : %d" "$version"
((version == 4 )) && printf " = kHFSPlusVersion"
((version == 5 )) && printf " = kHFSXVersion"
printf "\n"
((attributes)) && {
attributestext=$(
((attributes & 0x00000080)) && printf ",VolumeHardwareLock"
((attributes & 0x00000100)) && printf ",VolumeUnmounted"
((attributes & 0x00000200)) && printf ",VolumeSparedBlocks"
((attributes & 0x00000400)) && printf ",VolumeNoCacheRequired"
((attributes & 0x00000800)) && printf ",BootVolumeInconsistent"
((attributes & 0x00001000)) && printf ",CatalogNodeIDsReused"
((attributes & 0x00002000)) && printf ",VolumeJournaled"
((attributes & 0x00004000)) && printf ",VolumeInconsistent"
((attributes & 0x00008000)) && printf ",VolumeSoftwareLock"
((attributes & 0x40000000)) && printf ",ContentProtection"
((attributes & 0x80000000)) && printf ",UnusedNodeFix"
((attributes & 0x3fff007f)) && printf ",0x%08x?" $((drAtrb & 0x3fff007f))
)
printf "004: attributes : 0x%08x = %s\n" "$attributes" "${attributestext:1}"
}
printf "008: lastMountedVersion : 0x%08x = '%s'" "$lastMountedVersion" "$lastMountedVersionChars"
((lastMountedVersion == 0x31302E30 )) && printf " = kHFSPlusMountVersion" # '10.0'; (Mac OS 8.1 to 9.2.2 is '8.10')
((lastMountedVersion == 0x4846534a )) && printf " = kHFSJMountVersion"
((lastMountedVersion == 0x46534b21 )) && printf " = kFSKMountVersion"
printf "\n"
((journalInfoBlock || (attributes & 0x00002000) )) && printf "00c: journalInfoBlock : %d\n" "$journalInfoBlock"
printf "010: createDate : %s\n" "$( ((createDate )) && date -r $((createDate -2082844800)))"
printf "014: modifyDate : %s\n" "$( ((modifyDate )) && date -r $((modifyDate -2082844800)))"
printf "018: backupDate : %s\n" "$( ((backupDate )) && date -r $((backupDate -2082844800)))"
printf "01c: checkedDate : %s\n" "$( ((checkedDate)) && date -r $((checkedDate-2082844800)))"
printf "020: fileCount : %d\n" "$fileCount"
printf "024: folderCount : %d\n" "$folderCount"
printf "028: blockSize : %d\n" "$blockSize"
printf "02c: totalBlocks : %d\n" "$totalBlocks"
printf "030: freeBlocks : %d\n" "$freeBlocks"
printf "034: nextAllocation : %d\n" "$nextAllocation"
printf "038: rsrcClumpSize : %d\n" "$rsrcClumpSize"
printf "03c: dataClumpSize : %d\n" "$dataClumpSize"
printf "040: nextCatalogID : %d\n" "$nextCatalogID"
printf "044: writeCount : %d\n" "$writeCount"
((encodingsBitmap)) && {
encodings=$(
((encodingsBitmap & (1<< 0))) && printf ",MacRoman"
((encodingsBitmap & (1<< 1))) && printf ",MacJapanese"
((encodingsBitmap & (1<< 2))) && printf ",MacChineseTrad"
((encodingsBitmap & (1<< 3))) && printf ",MacKorean"
((encodingsBitmap & (1<< 4))) && printf ",MacArabic"
((encodingsBitmap & (1<< 5))) && printf ",MacHebrew"
((encodingsBitmap & (1<< 6))) && printf ",MacGreek"
((encodingsBitmap & (1<< 7))) && printf ",MacCyrillic"
((encodingsBitmap & (1<< 9))) && printf ",MacDevanagari"
((encodingsBitmap & (1<<10))) && printf ",MacGurmukhi"
((encodingsBitmap & (1<<11))) && printf ",MacGujarati"
((encodingsBitmap & (1<<12))) && printf ",MacOriya"
((encodingsBitmap & (1<<13))) && printf ",MacBengali"
((encodingsBitmap & (1<<14))) && printf ",MacTamil"
((encodingsBitmap & (1<<15))) && printf ",MacTelugu"
((encodingsBitmap & (1<<16))) && printf ",MacKannada"
((encodingsBitmap & (1<<17))) && printf ",MacMalayalam"
((encodingsBitmap & (1<<18))) && printf ",MacSinhalese"
((encodingsBitmap & (1<<19))) && printf ",MacBurmese"
((encodingsBitmap & (1<<20))) && printf ",MacKhmer"
((encodingsBitmap & (1<<21))) && printf ",MacThai"
((encodingsBitmap & (1<<22))) && printf ",MacLaotian"
((encodingsBitmap & (1<<23))) && printf ",MacGeorgian"
((encodingsBitmap & (1<<24))) && printf ",MacArmenian"
((encodingsBitmap & (1<<25))) && printf ",MacChineseSimp"
((encodingsBitmap & (1<<26))) && printf ",MacTibetan"
((encodingsBitmap & (1<<27))) && printf ",MacMongolian"
((encodingsBitmap & (1<<28))) && printf ",MacEthiopic"
((encodingsBitmap & (1<<29))) && printf ",MacCentralEurRoman"
((encodingsBitmap & (1<<30))) && printf ",MacVietnamese"
((encodingsBitmap & (1<<31))) && printf ",MacExtArabic"
((encodingsBitmap & (1<<33))) && printf ",MacSymbol"
((encodingsBitmap & (1<<34))) && printf ",MacDingbats"
((encodingsBitmap & (1<<35))) && printf ",MacTurkish"
((encodingsBitmap & (1<<36))) && printf ",MacCroatian"
((encodingsBitmap & (1<<37))) && printf ",MacIcelandic"
((encodingsBitmap & (1<<38))) && printf ",MacRomanian"
((encodingsBitmap & (1<<48))) && printf ",MacUkrainian"
((encodingsBitmap & (1<<49))) && printf ",MacFarsi"
((encodingsBitmap & (0xfffcff81 << 32))) && printf ",0x%016x?" $((encodingsBitmap & (0xfffcff81 << 32)))
)
printf "048: encodingsBitmap : 0x%016x = %s" "$encodingsBitmap" "${encodings:1}"
}
printf "\n"
printf "050: finderInfo:\n"
printf "050: Blessed System Folder : %s\n" "$(inodestring "$DEVICEID" "$((0x${finderInfo: 0: 8}))" )"
printf "054: Blessed System File : %s\n" "$(inodestring "$DEVICEID" "$((0x${finderInfo: 8: 8}))" )"
printf "058: Open-folder linked list : %s\n" "$(inodestring "$DEVICEID" "$((0x${finderInfo:16: 8}))" )"
printf "05c: Alternate OS blessed file/folder : %s\n" "$(inodestring "$DEVICEID" "$((0x${finderInfo:24: 8}))" )"
dumpencoding "060: Text encoding :" "$((0x${finderInfo:32: 8}))"
printf "064: OS X blessed folder : %s\n" "$(inodestring "$DEVICEID" "$((0x${finderInfo:40: 8}))" )"
printf "068: 64-bit VSDB volume id : 0x%016X => Volume UUID: %s\n" $(((0x${finderInfo:48:8} << 32) | 0x${finderInfo:56:8} )) "$(vsdbtouuid "${finderInfo:48:16}")"
printf "070: allocationFile : %s\n" "$(forkdatastring "$allocationFile" )"
printf "0c0: extentsFile : %s\n" "$(forkdatastring "$extentsFile" )"
printf "110: catalogFile : %s\n" "$(forkdatastring "$catalogFile" )"
printf "160: attributesFile : %s\n" "$(forkdatastring "$attributesFile" )"
printf "1b0: startupFile : %s\n" "$(forkdatastring "$startupFile" )"
echo
xxd -p -r <<< "$blockbytes" | xxd -c 16
if ((POFFSET < PLENGTH-4)); then
# queue up location of alternate HFS Plus Volume Header
# HFS+ volume starts at POFFSET - 2
endoffset=$((POFFSET - 2 + totalBlocks * (blockSize / 512)))
POFFSETS="_$((endoffset - 2))_$((endoffset - 1))${POFFSETS}"
#printf "queued alternate HFS+ Header: $POFFSETS\n"
fi
else
if (( 0x${blockbytes:0x20*2:8} == 0x4e585342 )); then # 'NXSB'
echo
echo "$PARTTYPE $PNUM @ ${PSTART}$( ((POFFSET > 0)) && printf "+%d" "$POFFSET" ): APFS Container contents"
else
HASH=$(xxd -p -r <<< "${blockbytes:96*2:416*2}" | xxd -p | md5)
FindHash "$PARTTYPE $PNUM @ ${PSTART}$( ((POFFSET > 0)) && printf "+%d" "$POFFSET" ): $(
((POFFSET==0)) && printf "VBR "
)contents" "$VBRHASHES" "$HASH"
fi
if [[ -n ${blockbytes//0/} ]]; then
xxd -p -r <<< "$blockbytes" | xxd -c 16
elif [[ -z $POFFSETS ]] && (( POFFSET < 2 )); then
POFFSETS="_$((POFFSET+1))"
#printf "queued after zero block: $POFFSETS\n"
fi
fi
done # while POFFSETS
done # while THEPART
done
#exit
if [[ -n $INPUTDISK ]]; then
echo "==============================================================================="
ioreg -w 0 -c IOMedia | sed -n -E "/^[ \|]*\+\-o (.*) <class IOMedia[^a-zA-Z]/,/^[ \|]+ }$/p" | {
sed -n -E "/^[ \|]*\+\-o (.*)/s//\1/p;/^[ \|]* \| (.*)/s//\1/p;"
} | {
perl -0777 -n -e 'while (/(^.*? <class IOMedia.*\n\{\n( .*\n)*^ "BSD Name" = "('"$INPUTDISK"'[^\d]|'"${INPUTDISK/s[0-9]*/}"'").*\n( .*\n)*?^}\n)/mg) { printf "$1\n" }'
}
echo "==============================================================================="
else
echo "==============================================================================="
ioreg -w 0 -c IOMedia | sed -n -E "/^[ \|]*\+\-o (.*) <class IOMedia[^a-zA-Z]/,/^[ \|]+ }$/p" | sed -n -E "/^[ \|]*\+\-o (.*)/s//\1/p;/^[ \|]* \| (.*)/s//\1/p;"
echo "==============================================================================="
bless --verbose --getBoot
echo "==============================================================================="
bless --verbose --info
echo "==============================================================================="
#ioreg -rw 0 -n AppleEFINVRAM 2> /dev/null | sed -n -E "/^[ \|]+[ ]+(\".*)$/s//\1/p;"
ioreg -lw0 -p IODeviceTree 2> /dev/null | sed -nE '/o chosen/,/}$/p ; /o option/,/}$/p ; /o aliases/,/}$/p ' | sed -nE "/^[ \|]+[ ]+(\".*)$/s// \1/p; / +\+\-o (.*) +<class ([^,]+).*/s//\1 <\2>/p"
echo "==============================================================================="
fi
@joevt
Copy link
Author

joevt commented Dec 2, 2022

Updates

March 16, 2024:

  • Fixes for Mac OS X 10.5 Leopard.
  • Fixed an issue where embedded HFS+ info was not output when a block is unexpectedly not all zeros.

July 28, 2023:

  • Bug fixes.

May 20, 2023:

  • Added 64-bit VSDB volume id to Volume UUID conversion for HFS and HFS+ partitions.

Dec 2, 2022:

  • Fixes for Mac OS X 10.4 Tiger.
  • Added the following (related to Mac booting from Open Firmware or EFI):
  • Apple Partition Map
  • APM Patch Driver
  • HFS/HFS+ Boot Blocks
  • HFS Wrapper
  • HFS Master Directory Block
  • HFS+ Volume Header
  • chosen, aliases
  • options (was previously output only for Intel Macs)
  • Pass a disk name (e.g. disk0) or a disk slice (e.g. disk0s2) to reduce the output to a single drive or partition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment