mirror of
https://github.com/vyos/vyos-build.git
synced 2025-10-01 20:28:40 +02:00
91 lines
2.7 KiB
Python
Executable File
91 lines
2.7 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
# Copyright: 2015 Bastian Blank
|
|
# License: MIT, see LICENSE.txt for details.
|
|
|
|
import array
|
|
import struct
|
|
import time
|
|
import sys
|
|
import os
|
|
|
|
from uuid import uuid4
|
|
|
|
|
|
class VHDFooter:
|
|
_struct = struct.Struct('>8sLLQL4sL4sQQ4sLL16sB427x')
|
|
size = _struct.size
|
|
|
|
vhd_timestamp_base = 946684800
|
|
|
|
def __init__(self, size, uuid=None, timestamp=None):
|
|
self.size = size
|
|
self.timestamp = timestamp or (int(time.time()) - self.vhd_timestamp_base)
|
|
self.uuid = uuid or uuid4()
|
|
|
|
@staticmethod
|
|
def _checksum(msg):
|
|
return 0x100000000 + ~sum(array.array("B", msg))
|
|
|
|
def _pack_geometry(self):
|
|
sectors = self.size // 512
|
|
|
|
if sectors > 65535 * 16 * 255:
|
|
sectors = 65535 * 16 * 255
|
|
|
|
if sectors >= 65535 * 16 * 63:
|
|
sectorsPerTrack = 255
|
|
heads = 16
|
|
cylinderTimesHeads = sectors // sectorsPerTrack
|
|
|
|
else:
|
|
sectorsPerTrack = 17
|
|
cylinderTimesHeads = sectors // sectorsPerTrack
|
|
|
|
heads = (cylinderTimesHeads + 1023) // 1024
|
|
|
|
if heads < 4:
|
|
heads = 4
|
|
if cylinderTimesHeads >= (heads * 1024) or heads > 16:
|
|
sectorsPerTrack = 31
|
|
heads = 16
|
|
cylinderTimesHeads = sectors // sectorsPerTrack
|
|
if cylinderTimesHeads >= (heads * 1024):
|
|
sectorsPerTrack = 63
|
|
heads = 16
|
|
cylinderTimesHeads = sectors // sectorsPerTrack
|
|
|
|
cylinders = cylinderTimesHeads // heads
|
|
|
|
return struct.pack('>HBB', cylinders, heads, sectorsPerTrack)
|
|
|
|
def _pack(self, checksum):
|
|
return self._struct.pack(
|
|
b'conectix', # Cookie
|
|
0x00000002, # Features
|
|
0x00010000, # File Format Version
|
|
0xffffffffffffffff, # Data Offset
|
|
self.timestamp, # Time Stamp
|
|
b'qemu', # Creator Application
|
|
0x00010000, # Creator Version
|
|
b'Wi2k', # Creator Host OS
|
|
self.size, # Original Size
|
|
self.size, # Current Size
|
|
self._pack_geometry(), # Disk Geometry
|
|
2, # Disk Type
|
|
checksum, # Checksum
|
|
self.uuid.bytes, # Unique Id
|
|
0, # Saved State
|
|
)
|
|
|
|
def pack(self):
|
|
c = self._checksum(self._pack(0))
|
|
return self._pack(c)
|
|
|
|
with open(sys.argv[1], 'rb+') as f:
|
|
f.seek(0, 2)
|
|
image_size = f.tell()
|
|
image_size_complete = image_size + VHDFooter.size
|
|
footer = VHDFooter(image_size)
|
|
f.write(footer.pack())
|