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 Jan 16, 2021

Download

cd ~/Downloads
curl -L https://gist.github.com/joevt/a99e3af71343d8242e0078ab4af39b6c/raw -o dumpvols.sh
xattr dumpvols.sh 2> /dev/null | grep com.apple.quarantine && xattr -d com.apple.quarantine dumpvols.sh
chmod +x dumpvols.sh

Run

sudo ./dumpvols.sh > dumpvols_1.txt 2>&1

Notes
Run the command before and after making partition changes. Use a different file name each time. This way you can compare the files to see what changed and to make sure the changes are correct.

This script does not list boot files. Do that manually for each partition you think should be bootable. The boot code in a VBR (also know as PBR) should show what file it's looking to boot. For Windows 7 and later, it should be BOOTMGR. That file should exist in the root directory with a Boot folder containing a BCD folder containing a BCD file. The BCD file contains a menu of items to be bootable and boot options. Use EasyBCD.exe to edit the BCD of any partition. The files may be invisible in macOS - type Command-Shift-Period to show invisible files in the Finder.

@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