Skip to content

Instantly share code, notes, and snippets.

@joevt
Last active August 28, 2025 07:03
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 Dec 29. 2020
# 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
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 "\
""
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
}
disklist="$(diskutil list)"
echo "$disklist"
echo
diskutil apfs list
DRIVELIST=$(sed -n -E "/^[ ]*0: [ ]{0,25}([A-Za-z_]+)[ ]*\*[0-9.]+ [TGMK]B[ ]+(disk[0-9]+)$/s//\1_\2/p;/^[ ]*0: [ ]{0,26} .* \*[0-9.]+ [TGMK]B[ ]+(disk[0-9]+)$/s//whole_\1/p" <<< "$disklist")
for PARTDRIVE in $DRIVELIST;
do
DRIVE=$(expr "$PARTDRIVE" : '.*_\([^_]*\)')
PTYPE=$(expr "$PARTDRIVE" : '\(.*\)_[^_]*')
echo "==============================================================================="
diskutiloutput="$(sed -nE '/\/dev\/'$DRIVE' /,/^$/ p' <<< "${disklist}")"
echo "$diskutiloutput"
echo "---------------------------------------------"
diskinfo="$(diskutil info $DRIVE)"
echo "$diskinfo"
echo
BLOCKSIZE=$(sed -nE '/^ *Device Block Size: +([0-9]+).*/s//\1/p' <<< "$diskinfo")
if [[ -z $BLOCKSIZE ]]; then
BLOCKSIZE=512
fi
DEVLIST=$(echo "$diskutiloutput" | sed -n -E "/^.* (disk[0-9]+s[0-9]+)$/s//\1/p")
for THEDEV in $DEVLIST; do
echo "---------------------------------------------"
diskutil info $THEDEV
done
if [ "$PTYPE" = "Apple_partition_scheme" ]; then
pdisk -r -l "/dev/$DRIVE"
pdisk -r -l -f "/dev/$DRIVE"
# use the same bytes as MBR hash even though Block0 contents are totally different
HASH=$(dd if="/dev/$DRIVE" bs=1 count=446 2> /dev/null | xxd -p -l 440 | md5)
FindHash "Block0 contents" "$MBRHASHES" "$HASH"
dd if="/dev/$DRIVE" bs=1 count=512 2> /dev/null | xxd -c 16
elif [ "$PTYPE" = "GUID_partition_scheme" -o "$PTYPE" = "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 "$gptoutput"
echo "$gptoutput2"
echo "$fdiskoutput"
HASH=$(dd if="/dev/$DRIVE" bs=1 count=446 2> /dev/null | xxd -p -l 440 | md5)
FindHash "MBR contents" "$MBRHASHES" "$HASH"
dd if="/dev/$DRIVE" bs=1 count=512 2> /dev/null | xxd -c 16
if [ "$PTYPE" = "FDisk_partition_scheme" ]; then
PARTLIST=$(echo "$fdiskoutput" | sed -n -E "/^[ \*]+([0-9])\: .*\[[ ]*([0-9]+) \-[ ]+([1-9][0-9]*)\].*$/s//\1_\2_\3/p")
PARTTYPE="MBR"
else
HASH=$(dd if="/dev/$DRIVE" bs=1 skip=$((BLOCKSIZE + 96)) count=416 2> /dev/null | xxd -p -l 440 | md5)
FindHash "GPT Header @ 1: GPT Header contents" "$VBRHASHES" "$HASH"
dd if="/dev/$DRIVE" bs=1 skip=$BLOCKSIZE count=$BLOCKSIZE 2> /dev/null | xxd -c 16
PARTLIST=$(echo "$gptoutput" | sed -n -E "/^[ ]+([0-9]+)[ ]+([0-9]+)[ ]+([0-9]+)[ ]+GPT part \-.*$/s//\3_\1_\2/p")
PARTTYPE="GPT"
fi
for THEPART in $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]*\)')
HASH=$(dd if="/dev/$DRIVE" bs=1 skip=$((PSTART * BLOCKSIZE + 96)) count=416 2> /dev/null | xxd -p -l 440 | md5)
FindHash "$PARTTYPE $PNUM @ $PSTART: VBR contents" "$VBRHASHES" "$HASH"
dd if="/dev/$DRIVE" bs=1 skip=$((PSTART * BLOCKSIZE)) count=$BLOCKSIZE 2> /dev/null | xxd -c 16
done
elif [ "$PTYPE" = "whole" ]; then
HASH=$(dd if="/dev/$DRIVE" bs=1 count=416 2> /dev/null | xxd -p -l 440 | md5)
FindHash "0 @ 0: VBR contents" "$VBRHASHES" "$HASH"
dd if="/dev/$DRIVE" bs=512 count=1 2> /dev/null | xxd -c 16
else
echo "Unknown partition scheme"
fi
done
echo "==============================================================================="
ioreg -rw 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 | sed -n -E "/^[ \|]+[ ]+(\".*)$/s//\1/p;"
echo "==============================================================================="
@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

Aug 28, 2025:

  • Fixes and improvements.

Mar 20, 2025:

  • Add MFS partition support.
  • Add support for whole disk partition (no partition map).

Mar 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.

Jul 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.

@divinity76
Copy link

what is b3e20f39f29211d697a400306543ecac ?

@joevt
Copy link
Author

joevt commented Mar 15, 2025

what is b3e20f39f29211d697a400306543ecac ?

It is b3e20f39-f292-11d6-97a4-00306543ecac or HFS_UUID_NAMESPACE_ID - a 128-bit UUID which is prepended to the 64-bit VSDB volume id of a HFS partition. The 192-bit result is passed to MD5 to generate a 128-bit Mac OS X volume UUID.

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