Skip to content

Instantly share code, notes, and snippets.

@andshrew
Last active March 28, 2024 20:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andshrew/1d0b5e35308a6fd9770831e47950be0a to your computer and use it in GitHub Desktop.
Save andshrew/1d0b5e35308a6fd9770831e47950be0a to your computer and use it in GitHub Desktop.
PS3 Linux / FreeBSD Drive Decryption Notes

These are the steps I took on Linux Mint using the PS3 HDD decryption helper

Reference discussion: HDD mounting and decryption on Linux

Install qemu for PowerPC64 and download FreeBSD Image

  1. qemu-system-ppc64 is used to emulate a PowerPC CPU
    Install via:
    sudo apt install qemu-system-ppc
  2. FreeBSD has some instructions for using qemu with PowerPC64 here.
    They have pre-built disk files which you can download here.
    Download and extract:
    https://artifact.ci.freebsd.org/snapshot/head/latest_vm/powerpc/powerpc64/disk-pseries.qcow2.zst
  3. You should now have a disk image disk-pseries.qcow2
    I saved this to: /home/andrew/Downloads/disk-pseries.qcow2

Decrypt PS3 drive with the decryption helper in Linux

  1. Use KO Manager to load modules (only "swap16-ecb.ko" was loaded)
    To create the mapper I ran the commands from the mounter script manually, to avoid automatically mounting them in Linux
    Note commands for a Slim PS3 on /dev/sdb
sudo cryptsetup create -c bswap16-ecb -d /dev/zero ps3hdd-bs /dev/sdb
sudo cryptsetup create -c aes-xts-plain64 -d ${HOME}/ps3/keys/ata_key.bin -s 256 ps3hdd /dev/mapper/ps3hdd-bs
sudo kpartx -a /dev/mapper/ps3hdd
sudo cryptsetup create -c aes-xts-plain64 -d ${HOME}/ps3/keys/vflash_key.bin -s 256 -p 8 ps3vflash /dev/mapper/ps3hdd1
sudo kpartx -a /dev/mapper/ps3vflash

Passthrough /dev/mapper/ps3hdd2 to FreeBSD PowerPC64 VM

  1. Launch the VM with this command. Make sure disk-pseries.qcow2 path is where you saved the disk image file earlier.
    This starts a PowerPC64 VM with 2 vCPU, 2GB RAM, and two drives attached (the disk image you downloaded, and /dev/mapper/ps3hdd2). The other commands come from the FreeBSD wiki
sudo qemu-system-ppc64 -smp 2 -m 2g \
    -drive file=/dev/mapper/ps3hdd2,format=raw,if=virtio \
    -drive file=/home/andrew/Downloads/disk-pseries.qcow2,format=qcow2,if=virtio \
    -net nic,model=virtio \
    -machine pseries,cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken \
    -vga none -nographic
  1. It will start outputting to the terminal. Even though it is emulated, it booted very quickly for me using a 12th gen i5 CPU.
  2. Login with root and no password.
  3. The PS3 drive should be on /dev/vtbd1 - but confirm this is the case with geom disk list
root@:~ # geom disk list
Geom name: vtbd1
Providers:
1. Name: vtbd1
   Mediasize: 317656989696 (296G)
   Sectorsize: 512
   Mode: r0w0e0
   descr: (null)
   ident: (null)
   rotationrate: unknown
   fwsectors: 63
   fwheads: 16
  1. You can also validate it's the correct path with file -s /dev/vtbd1
root@:~ # file -s /dev/vtbd1
/dev/vtbd1: Unix Fast File system [v2] (big-endian) last mounted .....
  1. At this point you should be able to freely use the drive.
root@:~ # mkdir dev_hdd0
root@:~ # mount /dev/vtbd1 dev_hdd0
root@:~ # ls -la dev_hdd0
total 40
drwxr-xr-x  10 root wheel 512 Nov  8 16:33 .
drwxr-xr-x   4 root wheel 512 Nov  8 20:44 ..
drwx-----x   5 root wheel 512 Jan  1  2012 crash_report
drwx------   2 root wheel 512 Jan  1  2012 data
drwx------   3 root wheel 512 Jan  1  2012 drm
drwx------   3 root wheel 512 Jan  1  2012 home
drwx------   3 root wheel 512 Jan  1  2012 mms
-rw-r--r--   1 root wheel   0 Nov  8 16:33 test
drwx------   5 root wheel 512 Jan  1  2012 tmp
drwx------   2 root wheel 512 Jan  1  2012 vm
drwx------   4 root wheel 512 Jan  1  2012 vsh
root@:~ # umount dev_hdd0

Note file test which I created (presumably the dates are 2012 because I didn't set the PS3 date when I formatted this drive)

Or run fsck to try and repair a corrupted drive

root@:~ # fsck -y /dev/vtbd1
** /dev/vtbd1
** Last Mounted on /cell_mw_cfs
** Phase 1 - Check Blocks and Sizes
** Phase 2 - Check Pathnames
UPDATE FILESYSTEM TO TRACK DIRECTORY DEPTH? yes
** Phase 3 - Check Connectivity
** Phase 4 - Check Reference Counts
** Phase 5 - Check Cyl groups
FREE BLK COUNT(S) WRONG IN SUPERBLK
SALVAGE? yes
SUMMARY INFORMATION BAD
SALVAGE? yes
BLK(S) MISSING IN BIT MAPS
SALVAGE? yes
394087 files, 259173843 used, 42411811 free (69523 frags, 5292786 blocks, 0.0% fragmentation)
***** FILE SYSTEM MARKED CLEAN *****
***** FILE SYSTEM WAS MODIFIED *****

Shutdown and tidy up

  1. Unmount drive in the FreeBSD VM and shut it down.
  2. Use PS3 HDD Umounter in Linux to tidy up the mapper.

Migrating PS3 Slim Hard Disk Drive Data

Disclaimer:- This document is not a tutorial. The information is shared for the benefit of anyone attempting data recovery and/or migration on a PS3 hard disk drive

Background

This is a record of the steps which I took to migrate the data on my PS3s hard disk drive to a new larger drive, without having to use the slow and often unreliable built in backup tool.

This procedure is only possible on a PS3 where Custom Firmware has first been installed to obtain the consoles eid_root_key, used for the per-console disk drive encryption. Once this key was obtained, the PS3 was reverted to Official Firmware and all steps below were subsequently performed after the PS3 has been returned to Official Firmware.

This procedure was done as part of a data recovery process on my original disk drive. The goal was to repair that drive and, if successful, migrate the data from the old mechanical drive to a new SSD drive. As any kind of data recovery requires Custom Firmware in order to be able to access the drive encryption key, an additional goal was to do this in such a way that minimal evidence was left on the system that might indicate Custom Firmware was installed, such than when the system was returned to Official Firmware it would not be at risk of either a hardware or account ban.

The PS3 was reporting that the System Storage was corrupted and that it could not be repaired. In troubleshooting this I had cloned the original mechanical 640GB disk drive to a new 1.5TB SSD disk drive. The corruption that the PS3 was reporting was repairable via a simple fsck on the dev_hdd0 partition of the drive, performed while the drive was mounted within a PowerPC64 FreeBSD VM (after having been decrypted by a Linux Mint system).

Given the simplicity of the fix, it's disappointing that the PS3 was seemingly unable run an fsck itself...

With the drive working again I was left with the issue of having a system that could only address 640GB of the 1.5TB drive it has been cloned to. As there is no native facility for an Official Firmware PS3 to resize the file system, and as I was not comfortable in my ability to attempt to manually resize it by manipulating the partition table, I opted to copy the files to an intermediary disk. I would then allow the PS3 to format the 1.5TB drive, and then copy the files back. The procedure took ~11 hours in total to relocate the ~530GB of data between drives.

If you were copying from an old drive to a brand new drive these steps could be adjusted to avoid copying to the intermediary drive, and instead copying directly from the old and to the new drive. This should reduce the time taken to complete the procedure in half, but this would require careful adjustment of the PS3 mounting commands to enable two drives to be decrypted and accessed at once.

Please note this procedure was performed using a PS3 Slim model. The exact commands that should be used, and even the viability of this method, is going to depend on what model of PS3 you have. Should you attempt to follow this please review the scripts within the PS3 HDD decryption helper to understand the commands which are being used, and review information from this discussion on PS3 hard drive decryption.

Post-procedure Hindsight

  • It would likely have been more efficient to do the initial copy as a disk image, rather than copying the files to the intermediary disk. This would likely have reduced the initial copy time by half (as taking an image is faster than copying hundreds of thousands of files), and it could avoid having to use the emulated PowerPC64 FreeBSD VM until it was time to move the data to the new drive.
  • The file copy times may have been reduced by assigning the FreeBSD VM additional vCPU. These notes assign 2x vCPU -smp 2 but for the copy to the new drive I adjusted this to 4x vCPU. This copy completed ~1 hour quicker than the initial copy, but it's unclear how much of that is down to the increased vCPU vs the increased speed of reading from the intermediary mechanical drive compared with writing to it. All drives were connected to the system using 5Gbit USB 3.
  • It may have been more efficient to use rsync rather than cp to transfer the files.

Summary of Steps

At a high level, the process of migrating the data between two disk drives (via an intermediary drive) from a PS3 Slim system involves these steps:

  1. Decrypting the old PS3 hard drive using a Linux Mint system
  2. Passing the decrypted dev_hdd0 partition through to a PowerPC64 FreeBSD VM
    This enables read/write access to the big-endian Unix File System v2 used on the partition
  3. Copying all files from dev_hdd0 to another UFS v2 volume
    This partition contains all user data
  4. Creating an image of dev_flash2
    This partition contains the PS3 configuration database xRegistry.sys
  5. Format the new drive in the PS3
  6. Repeat steps 1 and 2 for the new drive
  7. Copy the dev_hdd0 files to the new drive
  8. Apply the dev_flash2 image to the new drive
  9. Connect the new drive to the PS3
  10. Procedure complete

Pre-requisites

  • A PS3 Slim system
  • The eid_root_key from the PS3 which formatted the drives
    This requires a full Custom Firmware installation to obtain, but the console can be returned to Official Firmware after obtaining it. This key is specific to the console and will work for all drives that the console has formatted
  • A Linux Mint system
    Or a Linux of your choice if you know what you're doing
  • PS3 HDD decryption helper
  • qemu-system-ppc64 and a PowerPC64 FreeBSD system image
    See for more detail on installing and preparing qemu
  • An intermediary disk drive to copy the PS3 data

Step-by-Step

Remeber, this procedure contains commands specific to the PS3 Slim

  1. Use PS3 KO Manager.sh option 1 to load modules
    Only swap16-ecb.ko is loaded

  2. Decrypt the PS3 drive
    I did this by running commands from PS3 HDD Mounter.sh manually so as to avoid automatically mounting the decrypted partitions in the Linux system
    The PS3 drive is on /dev/sdc

    PS3_DEV_NAME=/dev/sdc
    sudo cryptsetup create -c bswap16-ecb -d /dev/zero ps3hdd-bs ${PS3_DEV_NAME}
    sudo cryptsetup create -c aes-xts-plain64 -d ${HOME}/ps3/keys/ata_key.bin -s 256 ps3hdd /dev/mapper/ps3hdd-bs
    sudo kpartx -a /dev/mapper/ps3hdd
    sudo cryptsetup create -c aes-xts-plain64 -d ${HOME}/ps3/keys/vflash_key.bin -s 256 -p 8 ps3vflash /dev/mapper/ps3hdd1
    sudo kpartx -a /dev/mapper/ps3vflash
    
  3. Start the ppc64 FreeBSD VM and pass the decrypted PS3 partition, and the intermediary backup drive through to it
    See here for more detail on installing and preparing qemu
    /home/andrew/Downloads/disk-pseries.qcow2 is the FreeBSD boot and system drive
    /dev/sdb is the device I will use to backup the PS3 data. These steps destroy all existing data on the device
    /dev/mapper/ps3hdd2 is the PS3 dev_hdd0 partition

    sudo qemu-system-ppc64 -smp 2 -m 2g \
        -drive file=/dev/mapper/ps3hdd2,format=raw,if=virtio \
        -drive file=/dev/sdb,format=raw,if=virtio \
        -drive file=/home/andrew/Downloads/disk-pseries.qcow2,format=qcow2,if=virtio \
        -net nic,model=virtio \
        -machine pseries,cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken \
        -vga none -nographic
    
  4. Prepare the backup drive. Note these steps will destroy any data on /dev/sdb
    See this useful guide for FreeBSD disk setup commands
    I did try to use a Linux ext4 partition for this, but I found FreeBSD was not able to reliably write to the drive, so instead opted to use a native disk format
    /dev/sdb is mapped to /dev/vtbd1 within the FreeBSD VM
    1. Create a new GPT partition table
    2. Create a UFS partition occupying all space available on the device

    gpart destroy -F vtbd1
    gpart create -s gpt vtbd1
    gpart add -t freebsd-ufs -l ps3backup -b 1M vtbd1
    newfs -U /dev/gpt/ps3backup

    Terminal output from the commands

     root@:~ # gpart destroy -F vtbd1
     vtbd1 destroyed
     root@:~ # gpart create -s gpt vtbd1
     vtbd1 created
     root@:~ # gpart add -t freebsd-ufs -l ps3backup -b 1M vtbd1
     vtbd1p1 added
     root@:~ # newfs -U /dev/gpt/ps3backup 
     /dev/gpt/ps3backup: 1023999.0MB (2097149912 sectors) block size 32768, fragment size 4096
             using 1638 cylinder groups of 625.22MB, 20007 blks, 80128 inodes.
             with soft updates
     super-block backups (for fsck_ffs -b #) at:
     192, 1280640, 2561088, 3841536, 5121984, 6402432, 7682880, 8963328, 10243776, 11524224, 12804672, 14085120, 15365568, 16646016, 17926464, 19206912,
     ...
     ...
     2070484608, 2071765056, 2073045504, 2074325952, 2075606400, 2076886848, 2078167296, 2079447744, 2080728192, 2082008640, 2083289088, 2084569536,
     2085849984, 2087130432, 2088410880, 2089691328, 2090971776, 2092252224, 2093532672, 2094813120, 2096093568
    
  5. Mount the backup drive to the backup directory
    mkdir backup
    mount /dev/gpt/ps3backup backup

  6. Mount the PS3 dev_hdd0
    /dev/mapper/ps3hdd2 is mapped to /dev/vtbd2 within the FreeBSD VM
    Use file -s /dev/vtbd2 to confirm this is the partition

    root@:~ # file -s /dev/vtbd2
    /dev/vtbd2: Unix Fast File system [v2] (big-endian) last mounted on /cell_mw_cfs, last written at Thu Nov  9 22:18:53 2023, clean flag 1, readonly flag 0, number of blocks 311386280, number of data blocks 301585654, number of cylinder groups 3311, block size 16384, fragment size 2048, average file size 16384, average number of files in dir 64, pending blocks to free 0, pending inodes to free 0, system-wide uuid 0, minimum percentage of free blocks 8, TIME optimization
    

    Note that the PS3 seemingly mounts the drive at /cell_mw_cfs, so for consistency with OFW we should mount it there too on this system (while it likely doesn't matter, the last mount path could potentially be logged by the PS3)
    mkdir /cell_mw_cfs
    mount /dev/vtbd2 /cell_mw_cfs

  7. Check if any symlinks exist on the PS3 drive
    I was unsure how symlinks may copy if they existed, so would want to check manually. As it happens, there were none
    find /cell_mw_cfs/. -type l -ls

  8. Copy all files from the PS3 dev_hdd0 to the backup drive

    1. Count files and directories on PS3 drive for comparison after the copy
      find /cell_mw_cfs/ -type f -print | wc -l
      find /cell_mw_cfs/ -type d -print | wc -l

      root@:~ # find /cell_mw_cfs/ -type f -print | wc -l
      370846
      root@:~ # find /cell_mw_cfs/ -type d -print | wc -l
      23237
      
    2. Make backup directory and begin copy
      mkdir backup/ps3
      cp -Rp /cell_mw_cfs/ backup/ps3/
      This step will take a number of hours, depending on the size of your data and speed of the drives... but it will still be several times faster than the PS3 builtin backup utility!

      root@:~ # cp -Rp /cell_mw_cfs/ backup/ps3/
      root@:~ #
      
    3. Check file and directory count on backup drive to compare with the original numbers
      find backup/ps3/ -type f -print | wc -l
      find backup/ps3/ -type d -print | wc -l

      root@:~ # find backup/ps3/ -type f -print | wc -l
      370846
      root@:~ # find backup/ps3/ -type d -print | wc -l
      23237
      
  9. Unmount the drives
    umount backup
    umount /cell_mw_cfs

  10. Shutdown the FreeBSD VM

  11. Create an image of the dev_flash2 partition from the PS3 drive
    sudo dd if=/dev/mapper/ps3vflash3 of=dev_flash2.img status=progress

    andrew@mint:~/ps3$ sudo dd if=/dev/mapper/ps3vflash3 of=dev_flash2.img status=progress         
    32768+0 records in
    32768+0 records out
    16777216 bytes (17 MB, 16 MiB) copied, 0.842484 s, 19.9 MB/s
    
  12. Use PS3 HDD Umounter.sh to remove PS3 drive mapper

  13. Shutdown Linux Mint or "safely" disconnect the PS3 drive from the system

  14. Connect the new drive to the PS3, and format it via Safe Mode
    Option 5 Restore PS3 System
    Turn the system off during the initial setup process (prompt to select language), and disconnect from PS3

  15. Connect the new drive to Linux Mint, repeat steps 1, 2, 3, 5 and 6 (do not repeate step 4 otherwise you will erase the backup data!) to decrypt the drive, and prepare the FreeBSD VM
    Double check device names are the same as before
    With the newly formatted PS3 drive mounted, running ls you can see it doesn't even have a home directory created yet (as it was turned off during the initial setup)

    root@:~ # ls -la /cell_mw_cfs/
    total 32
    drwxr-xr-x   8 root wheel 512 Jan  1  2012 .
    drwxr-xr-x  19 root wheel 512 Nov 10 07:10 ..
    drwx-----x   5 root wheel 512 Jan  1  2012 crash_report
    drwx------   3 root wheel 512 Jan  1  2012 drm
    drwx------   3 root wheel 512 Jan  1  2012 mms
    drwx------   4 root wheel 512 Jan  1  2012 tmp
    drwx------   2 root wheel 512 Jan  1  2012 vm
    drwx------   4 root wheel 512 Jan  1  2012 vsh
    

    df confirms the full space is available on the partition

    root@:~ # df /dev/vtbd2
    Filesystem          1K-blocks      Used      Avail Capacity  Mounted on
    /dev/vtbd2         1547482120    510360 1423173192     0%    /cell_mw_cfs
    

    file -s displays some file system info

        root@:~ # file -s /dev/vtbd2
        /dev/vtbd2: Unix Fast File system [v2] (big-endian) last mounted on /cell_mw_cfs, 
        last written at Fri Nov 10 07:13:16 2023, clean flag 0,
        readonly flag 0, number of blocks 399410172,
        number of data blocks 386870530, number of cylinder groups 5405,
        block size 16384, fragment size 4096, average file size 16384,
        average number of files in dir 64, pending blocks to free 0,
        pending inodes to free 0, system-wide uuid 0,
        minimum percentage of free blocks 8, TIME optimization
    
  16. Delete all files and folders on the new PS3 dev_hdd0
    rm -Rf /cell_mw_cfs/

    root@:~ # rm -Rf /cell_mw_cfs/
    rm: /cell_mw_cfs/: Device busy
    root@:~ # ls -la /cell_mw_cfs/
    total 8
    drwxr-xr-x   2 root wheel 512 Nov 10 07:22 .
    drwxr-xr-x  19 root wheel 512 Nov 10 07:10 ..
    
  17. Copy the backed up files to the new PS3 drive
    cp -Rp backup/ps3/ /cell_mw_cfs/

    root@:~ # cp -Rp backup/ps3/ /cell_mw_cfs/
    root@:~ # 
    
  18. Confirm the file and directory counts match previous numbers
    find /cell_mw_cfs/ -type f -print | wc -l
    find /cell_mw_cfs/ -type d -print | wc -l

    root@:~ # find /cell_mw_cfs/ -type f -print | wc -l
        370846
    root@:~ # find /cell_mw_cfs/ -type d -print | wc -l
        23237
    

    ls output

    root@:~ # ls -la /cell_mw_cfs/
    total 76
    drwxr-xr-x   17 root wheel  512 Mar  8  2023 .
    drwxr-xr-x   19 root wheel  512 Nov 10 07:10 ..
    drwx-----x    5 root wheel  512 Jan 13  2011 crash_report
    drwx------    2 root wheel  512 Jul 17  2021 data
    drwx------    5 root wheel  512 Jun 25  2011 drm
    drwxr-xr-x  321 root wheel 7168 Nov  3 16:31 game
    drwx------    7 root wheel  512 Oct  1  2011 home
    drwx------    9 root wheel  512 Jan 13  2011 mms
    drwx------   48 root wheel 1024 Jul  3  2013 music
    drwx------   10 root wheel  512 Nov 27  2014 photo
    drwx------    3 root wheel  512 Apr 27  2008 savedata
    drw-rw-rw-    2 root wheel 4608 Dec 19  2013 theme
    drwx------   18 root wheel  512 Nov  8 19:27 tmp
    drwx---rwx    3 root wheel  512 Jul  5  2012 updater
    drwx------    5 root wheel  512 Oct 17  2013 video
    drwx------    2 root wheel  512 Mar  8  2023 vm
    drwx------    7 root wheel  512 Mar  9  2023 vsh
    

    df output

    root@:~ # df /dev/vtbd2
    Filesystem  1K-blocks      Used     Avail Capacity  Mounted on
    /dev/vtbd2 1547482120 518723412 904960140    36%    /cell_mw_cfs
    
  19. Unmount drives
    umount backup
    umount /cell_mw_cfs

  20. Run an fsck on the PS3 partition
    This isn't really required, but I noted that the man page for fsck_ufs suggested that the -E option may perform a TRIM on the SSD for this partition, however it's unclear if such instructions would even be passed back through to the physical controller
    Given that the PS3 does not support this feature, it may be beneficial to be able to periodically run this via mounting the drive in a FreeBSD system - if it works in this configuration

    fsck_ufs -Ey /dev/vtbd2

    root@:~ # fsck_ufs -Ey /dev/vtbd2
    ** /dev/vtbd2
    ** Last Mounted on /cell_mw_cfs
    ** Phase 1 - Check Blocks and Sizes
    ** Phase 2 - Check Pathnames
    ** Phase 3 - Check Connectivity
    ** Phase 4 - Check Reference Counts
    ** Phase 5 - Check Cyl groups
    394083 files, 129680853 used, 257189677 free (11109 frags, 64294642 blocks, 0.0% fragmentation)
    
    ***** FILE SYSTEM IS CLEAN ***** 
    

    file -s output

    root@:~ # file -s /dev/vtbd2
    /dev/vtbd2: Unix Fast File system [v2] (big-endian) last mounted on /cell_mw_cfs, last written at Fri Nov 10 12:07:42 2023, clean flag 1, readonly flag 0, number of blocks 399410172, number of data blocks 386870530, number of cylinder groups 5405, block size 16384, fragment size 4096, average file size 16384, average number of files in dir 64, pending blocks to free 0, pending inodes to free 0, system-wide uuid 0, minimum percentage of free blocks 8, TIME optimization
    
  21. Shutdown the FreeBSD VM

  22. Restore the dev_flash2 image to the new drive
    sudo dd if=dev_flash2.img of=/dev/mapper/ps3vflash3 status=progress

    andrew@mint:~/ps3$ sudo dd if=dev_flash2.img of=/dev/mapper/ps3vflash3 status=progress     
    14692864 bytes (15 MB, 14 MiB) copied, 1 s, 14.7 MB/s
    32768+0 records in
    32768+0 records out
    16777216 bytes (17 MB, 16 MiB) copied, 1.20792 s, 13.9 MB/s
    
  23. Use PS3 HDD Umounter.sh to remove PS3 drive mapper

  24. Shutdown Linux Mint or "safely" disconnect the PS3 drive from the system

  25. Connect the PS3 drive to PS3

  26. Procedure complete

The PS3 booted up and was immediately usable, with all data available.
I did have to reactivate the console in order to be able to play any installed games (installed game information listed the buyer as blank).
It is unclear if this was caused solely by the disk migration, or if it is a consequence of having reinstalled firmware several times in my data recovery efforts.
Either way, the content was reactivated via:
PlayStation Network -> Account Management -> System Activation -> PS3 System -> Game
Repeat for Video if required, and for each PSN account if multiple are used on the system

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