In preparation for setting up and upgrading CRYSTALDRIN server to DSM 7.2, I tested out what’s the new process for creating an Xpenology VM in Proxmox.
I remember it being really complicated that involves a lot of commands.
With the recent development of interactive bootloaders, it was very easy now.
These are the notes I kept while doing it, in the order I needed them.
Create a boot disk
Step-by-step guide to create a boot disk for booting Xpenology bootloaders.
- Download the bootloader you intend to use.
- Extract the
.gzto.img. - Plug-in the USB flash drive.
- In a Mac terminal, run
diskutil list. - Note the disk number of of the USB flash drive in the list.
- Run
sudo dd if=arpl.img of=/dev/rdisk# bs=1m.- Replace
#with the disk number.
- Replace
Xpenology DSM bootloader list:
- https://github.com/pocopico/tinycore-redpill
- https://github.com/fbelavenuto/arpl/releases (not updated anymore)
- https://github.com/wjz304/arpl-i18n/releases (updated fork of arpl)
- https://github.com/AuxXxilium/arc
Mount the bootloader as a USB in Proxmox
In a VM, the bootloader image can be attached as a virtual USB disk instead.
The special configuration required for the virtual machine that simulates the U disk:
- Select the model as
q35. - Enable SeaBIOS, or select UEFI and enter BIOS to turn off secure boot.
- Cancel all Boot Order under Options.
- Edit
/etc/pve/qemu-server/101.conf.
Add the following line in (note to modify the mirror path):
args: -device 'nec-usb-xhci,id=usb-bus0,multifunction=on' -drive 'file=/path/to/arpl-sa6400.img,media=disk,format=raw,if=none,id=drive-disk-bootloader' -device 'usb-storage,bus=usb-bus0.0,port=1,drive=drive-disk-bootloader,id=usb-disk-bootloader,bootindex=999,removable=on'
Source: https://blog.jim.plus/blog/post/jim/synology-sa6400-with-i915
Patch AME for HEVC
AME patch is needed if you want support for HEVC encoding/decoding.
- Connect to SSH.
- Create the patch (below).
- Run
sudo python ame.py.
import hashlib
import os
r = ['669066909066906690', 'B801000000', '30']
s = [(0x1F28, 0), (0x48F5, 1), (0x4921, 1), (0x4953, 1), (0x4975, 1), (0x9AC8, 2)]
prefix = '/var/packages/CodecPack/target/usr'
so = prefix + '/lib/libsynoame-license.so'
print("Patching")
with open(so, 'r+b') as fh:
full = fh.read()
if hashlib.md5(full).digest().hex() != 'fcc1084f4eadcf5855e6e8494fb79e23':
print("MD5 mismatch")
exit(1)
for x in s:
fh.seek(x[0] + 0x8000, 0)
fh.write(bytes.fromhex(r[x[1]]))
lic = '/usr/syno/etc/license/data/ame/offline_license.json'
os.makedirs(os.path.dirname(lic), exist_ok=True)
with open(lic, 'w') as licf:
licf.write('[{"appType": 14, "appName": "ame", "follow": ["device"], "server_time": 1666000000, "registered_at": 1651000000, "expireTime": 0, "status": "valid", "firstActTime": 1651000001, "extension_gid": null, "licenseCode": "0", "duration": 1576800000, "attribute": {"codec": "hevc", "type": "free"}, "licenseContent": 1}, {"appType": 14, "appName": "ame", "follow": ["device"], "server_time": 1666000000, "registered_at": 1651000000, "expireTime": 0, "status": "valid", "firstActTime": 1651000001, "extension_gid": null, "licenseCode": "0", "duration": 1576800000, "attribute": {"codec": "aac", "type": "free"}, "licenseContent": 1}]')
print("Checking whether patch is successful...")
ret = os.system(prefix + "/bin/synoame-bin-check-license")
if ret == 0:
print("Successful, updating codecs...")
os.system(prefix + "/bin/synoame-bin-auto-install-needed-codec")
print("Done")
else:
print(f"Patch is unsuccessful, retcode = {ret}")
7.2:
import hashlib
import os
r = ['669066909066906690', 'B801000000', '30']
s = [(0x3718, 0), (0x60A5, 1), (0x60D1, 1), (0x6111, 1), (0x6137, 1), (0xB5F0, 2)]
prefix = '/var/packages/CodecPack/target/usr'
so = prefix + '/lib/libsynoame-license.so'
print("Patching")
with open(so, 'r+b') as fh:
full = fh.read()
if hashlib.md5(full).digest().hex() != '09e3adeafe85b353c9427d93ef0185e9':
print("MD5 mismatch")
exit(1)
for x in s:
fh.seek(x[0] + 0x8000, 0)
fh.write(bytes.fromhex(r[x[1]]))
lic = '/usr/syno/etc/license/data/ame/offline_license.json'
os.makedirs(os.path.dirname(lic), exist_ok=True)
with open(lic, 'w') as licf:
licf.write('[{"attribute": {"codec": "hevc", "type": "free"}, "status": "valid", "extension_gid": null, "expireTime": 0, "appName": "ame", "follow": ["device"], "duration": 1576800000, "appType": 14, "licenseContent": 1, "registered_at": 1649315995, "server_time": 1685421618, "firstActTime": 1649315995, "licenseCode": "0"}, {"attribute": {"codec": "aac", "type": "free"}, "status": "valid", "extension_gid": null, "expireTime": 0, "appName": "ame", "follow": ["device"], "duration": 1576800000, "appType": 14, "licenseContent": 1, "registered_at": 1649315995, "server_time": 1685421618, "firstActTime": 1649315995, "licenseCode": "0"}]')
print("Checking whether patch is successful...")
ret = os.system(prefix + "/bin/synoame-bin-check-license")
if ret == 0:
print("Successful, updating codecs...")
os.system(prefix + "/bin/synoame-bin-auto-install-needed-codec")
print("Done")
else:
print(f"Patch is unsuccessful, retcode = {ret}")
https://xpenology.com/forum/topic/65643-ame-30-patcher/
Related: Xpenology NVR Experiments: DVA1622 and DVA3221 and Enable IOMMU on Proxmox, Plus Real IOMMU Groups.