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())
 |